我们最近通过“guice-bridge”将 Guice 与 Jersey 集成,并且必须在此过程中升级依赖版本。但是随后在生产中的子资源(只有它们)有时会注入错误的 SecurityContext,而主体来自另一个线程!这种行为似乎是完全随机的,以前从未出现过。我们如何解决这个问题?
这是身份验证过滤器:
@Provider
@PreMatching
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// abort if user is not authenticated
requestContext.setSecurityContext(new MySecurityContext(...));
}
}
这是根资源:
@Path("/root-resource")
public class RootResource extends BaseResource {
@Path("{rootResourceId}/sub-resource")
public SubResource subResource(@PathParam("rootResourceId") String id) {
return SubResource.create(this, id);
}
...
}
这是子资源:
@Provider
public class SubResource extends BaseResource {
public static SubResource create(RootResource root, String rootResourceId) {
SubResource r = root.createSubResource(SubResource.class);
... // further setup
return r;
}
@PUT
@Path("{subResourceId}")
public void update(@PathParam("subResourceId") String subResourceId) {
checkUserHasAccessToResource(subResourceId, context); // BOOM ?#!
...
}
}
这是基类:
public abstract class BaseResource {
private ResourceContext resourceContext;
private SecurityContext securityContext;
protected final <T extends AuthResource> T createSubResource(Class<T> resourceClass) {
return resourceContext.getResource(resourceClass);
}
...
@Context
public void setResourceContext(ResourceContext resourceContext) {
this.resourceContext = resourceContext;
}
@Context
public void setSecurityContext(SecurityContext securityContext) {
this.securityContext = securityContext;
}
}
PS:我们使用 JDK7、Jersey 2.10.2 和 HK2 2.3.0-b04。
编辑
SecurityContext 实现:
public class MySecurityContext implements SecurityContext {
private final MyUserPrincipal userPrincipal;
private final boolean isSecure;
private final String authScheme;
public MySecurityContext(MyUserPrincipal userPrincipal, boolean isSecure, String authScheme) {
this.userPrincipal = userPrincipal;
this.isSecure = isSecure;
this.authScheme = authScheme;
}
@Override
public Principal getUserPrincipal() {
return userPrincipal;
}
@Override
public boolean isUserInRole(String role) {
return userPrincipal.isInRole(role);
}
@Override
public boolean isSecure() {
return isSecure;
}
@Override
public String getAuthenticationScheme() {
return authScheme;
}
}
还有校长:
public class MyUserPrincipal implements Principal {
private String userId;
private String userName;
private String[] roles;
public MyUserPrincipal(String userId, String userName, String[] roles) {
this.roles = roles;
this.userId = userId;
this.userName = userName;
}
@Override
public String getName() {
return userName;
}
@Override
public String toString() {
return userName + " (" + userId + ")";
}
@Override
public boolean isSecureLogin() {
return true;
}
@Override
public void reloadUser() {
}
public boolean isInRole(String role) {
...
}
}