Java 将SecurityContext信息和请求正文注入@BeanParam

Java 将SecurityContext信息和请求正文注入@BeanParam,java,rest,jax-rs,jersey-2.0,Java,Rest,Jax Rs,Jersey 2.0,目前,我正在MessageBodyReader中呈现一个命令对象,但我希望能够在@BeanParam中执行此操作: 插入一个从SecurityContext派生的字段(转换中是否有挂钩的地方?) 具有已由MessageBodyReader实现的字段注入 这可能吗 注意:下一步进行更新。我想可以使用@BeanParam。尽管您需要将SecurityContext注入bean并提取名称信息。 如果@BeanParam已更正,则无法实现这一点。你可以像现在这样使用MessageBodyReader,

目前,我正在
MessageBodyReader
中呈现一个命令对象,但我希望能够在
@BeanParam
中执行此操作:

  • 插入一个从
    SecurityContext
    派生的字段(转换中是否有挂钩的地方?)

  • 具有已由
    MessageBodyReader
    实现的字段注入


  • 这可能吗

    注意:下一步进行更新。我想可以使用
    @BeanParam
    。尽管您需要将
    SecurityContext
    注入bean并提取名称信息。


    如果
    @BeanParam
    已更正,则无法实现这一点。你可以像现在这样使用
    MessageBodyReader
    ,但在我看来,这更像是一种黑客行为。相反,我要实现这一点的方法是按照应该使用的方式使用框架组件,这涉及到自定义参数注入

    要实现这一点,您需要两件事,一个是提供参数值的
    ValueFactoryProvider
    ,另一个是带有自定义注释的
    InjectionResolver
    。我不会对下面的例子做太多解释,但是你可以在

    您可以像运行任何JUnit测试一样运行下面的示例。所有内容都包含在一个类中。这些是我使用的依赖项

    <dependency>
        <groupId>org.glassfish.jersey.test-framework.providers</groupId>
        <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
        <version>2.19</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.19</version>
        <scope>test</scope>
    </dependency>
    
    与前面的测试不同的是,我们需要注入整个
    SecurityContext
    ,而不是
    SecurityContext.Principal
    中的
    name
    。注入无法从
    主体
    获取名称,因此我们只能手动执行

    但最让我吃惊的是,我们能够注入
    RequestBody
    实体。我不知道这是可能的

    这是完整的测试

    import java.io.IOException;
    import java.security.Principal;
    import javax.ws.rs.BeanParam;
    import javax.ws.rs.Consumes;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.client.Entity;
    import javax.ws.rs.container.ContainerRequestContext;
    import javax.ws.rs.container.ContainerRequestFilter;
    import javax.ws.rs.container.PreMatching;
    import javax.ws.rs.core.Context;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import javax.ws.rs.core.SecurityContext;
    import org.glassfish.jersey.server.ResourceConfig;
    import org.glassfish.jersey.test.JerseyTest;
    import static org.junit.Assert.assertEquals;
    import org.junit.Test;
    
    public class CustomInjectTestTake2 extends JerseyTest {
        
        private static final String PRINCIPAL_NAME = "peeskillet";
        private static final String MESSAGE = "Hello World";
        private static final String RESPONSE = PRINCIPAL_NAME + ":" + MESSAGE;
        
        public static class CustomModel {
    
            @Context
            public SecurityContext securityContext;
            public RequestBody body;
        }
    
        public static class RequestBody {
    
            public String message;
        }
        
        @PreMatching
        public static class SecurityContextFilter implements ContainerRequestFilter {
    
            @Override
            public void filter(ContainerRequestContext requestContext) throws IOException {
                requestContext.setSecurityContext(new SecurityContext(){
                    public Principal getUserPrincipal() {
                        return new Principal() { 
                            public String getName() { return PRINCIPAL_NAME; }
                        };
                    }
                    public boolean isUserInRole(String role) { return false; }
                    public boolean isSecure() { return true;}
                    public String getAuthenticationScheme() { return null; }
                });   
            }  
        }
        
        @Path("test")
        public static class TestResource {
            @POST
            @Produces(MediaType.TEXT_PLAIN)
            @Consumes(MediaType.APPLICATION_JSON)
            public String post(@BeanParam CustomModel model) {
                return model.securityContext.getUserPrincipal().getName() 
                        + ":"  + model.body.message;
            }
        }
        
        @Override
        public ResourceConfig configure() {
            return new ResourceConfig(TestResource.class)
                    .register(SecurityContextFilter.class);
        }
        
        @Test
        public void should_return_name_with_body() {
            RequestBody body = new RequestBody();
            body.message = "Hello World";
            Response response = target("test").request()
                    .post(Entity.json(body));
            assertEquals(200, response.getStatus());
            String responseBody = response.readEntity(String.class);
            assertEquals(RESPONSE, responseBody);
            System.out.println(responseBody);
        }
    }
    
    另请参见:


    非常感谢你让我直截了当:D我本来打算使用这种方法(2周前),但当时我还处于技能提升阶段,这似乎是一个切线或过度工程,我有可能找到一个更合适的解决方案。是的,这似乎有点过分,但这实际上是Jersey处理所有
    @BeanParam
    @FormParam
    @PathParam
    ,等等的方式。所以我们可以遵循这个模式。。。或者不:-)@HassanSyed请查看我的更新。我想有了
    @BeanParam
    :-)这是可能的
    public static class CustomModel {
    
        @Context
        public SecurityContext securityContext;
        public RequestBody body;
    }
    
    public static class RequestBody {
    
        public String message;
    }
    
    import java.io.IOException;
    import java.security.Principal;
    import javax.ws.rs.BeanParam;
    import javax.ws.rs.Consumes;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.client.Entity;
    import javax.ws.rs.container.ContainerRequestContext;
    import javax.ws.rs.container.ContainerRequestFilter;
    import javax.ws.rs.container.PreMatching;
    import javax.ws.rs.core.Context;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import javax.ws.rs.core.SecurityContext;
    import org.glassfish.jersey.server.ResourceConfig;
    import org.glassfish.jersey.test.JerseyTest;
    import static org.junit.Assert.assertEquals;
    import org.junit.Test;
    
    public class CustomInjectTestTake2 extends JerseyTest {
        
        private static final String PRINCIPAL_NAME = "peeskillet";
        private static final String MESSAGE = "Hello World";
        private static final String RESPONSE = PRINCIPAL_NAME + ":" + MESSAGE;
        
        public static class CustomModel {
    
            @Context
            public SecurityContext securityContext;
            public RequestBody body;
        }
    
        public static class RequestBody {
    
            public String message;
        }
        
        @PreMatching
        public static class SecurityContextFilter implements ContainerRequestFilter {
    
            @Override
            public void filter(ContainerRequestContext requestContext) throws IOException {
                requestContext.setSecurityContext(new SecurityContext(){
                    public Principal getUserPrincipal() {
                        return new Principal() { 
                            public String getName() { return PRINCIPAL_NAME; }
                        };
                    }
                    public boolean isUserInRole(String role) { return false; }
                    public boolean isSecure() { return true;}
                    public String getAuthenticationScheme() { return null; }
                });   
            }  
        }
        
        @Path("test")
        public static class TestResource {
            @POST
            @Produces(MediaType.TEXT_PLAIN)
            @Consumes(MediaType.APPLICATION_JSON)
            public String post(@BeanParam CustomModel model) {
                return model.securityContext.getUserPrincipal().getName() 
                        + ":"  + model.body.message;
            }
        }
        
        @Override
        public ResourceConfig configure() {
            return new ResourceConfig(TestResource.class)
                    .register(SecurityContextFilter.class);
        }
        
        @Test
        public void should_return_name_with_body() {
            RequestBody body = new RequestBody();
            body.message = "Hello World";
            Response response = target("test").request()
                    .post(Entity.json(body));
            assertEquals(200, response.getStatus());
            String responseBody = response.readEntity(String.class);
            assertEquals(RESPONSE, responseBody);
            System.out.println(responseBody);
        }
    }