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
。我不会对下面的例子做太多解释,但是你可以在
<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);
}
}
另请参见:
@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);
}
}