我不确定这是否可能,但我正在尝试设置EJB + JAX-RS(Jersey)测试项目并使用@RolesAllowed注释。
我目前收到以下错误日志:
Warning: WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Security Exception
Severe: ejb.stateless_ejbcreate_exception
Warning: A system exception occurred during an invocation on EJB TestSB, method: public java.util.List rest.sb.TestSB.findAll()
Warning: javax.ejb.EJBException: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
相关课程:
application config.Java
@ApplicationPath("rest")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
packages("rest");
register(RolesAllowedDynamicFeature.class);
}
}
test SB facade.Java
@Local
public interface TestSBFacade {
public List<Test> findAll();
}
test SB.Java
@Stateless
@Path("secured/test")
public class TestSB implements TestSBFacade {
@DAO @Inject
private TestDAOFacade dao;
@Context
SecurityContext securityContext;
@Secured
@RolesAllowed({"READ"})
@Path("all")
@GET
@Produces(MediaType.APPLICATION_JSON)
@Override
public List<Test> findAll() {
//this works without the @RolesAllowed so it is a possible workaroud for now.
System.out.println(securityContext.isUserInRole("READ")); //output: true
return dao.findAll();
}
}
AU TH filter.Java
@Provider
@Secured //NameBinding
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String token = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
try {
verifyToken();
createSecurityContext();
} catch (Exception e) {
Logger.getLogger(AuthenticationFilter.class.getName()).log(Level.SEVERE, null, "Invalid or Expired JWT");
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}
}
我的SecurityContext已设置并正常工作,@ RolesAllowed似乎是问题,因为我没有错误,如果我删除它并且JSON正确返回到前端。保持@RolesAllowed会导致开头提到的错误。
但是,我想使用方便的注释,而不是在isUserInRole IF语句中嵌入每个方法。任何帮助和见解都非常感谢。
显然,由于使用@RolesAllowed
的EJB和JAX-RS实现,它们并不能很好地协同工作。所以我决定创建自己的Annotation并在ApplicationConfig.java
中注册我自己的DynamicFeature。
authorized.Java
@Documented
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Authorized {
public String[] value() default "";
}
authorization dynamic feature.Java
public class AuthorizationDynamicFeature implements DynamicFeature {
@Override
public void configure(final ResourceInfo resourceInfo, final FeatureContext featureContext) {
Authorized auth = new AnnotatedMethod(resourceInfo.getResourceMethod()).getAnnotation(Authorized.class);
if (auth != null) {
featureContext.register(new AuthorizationRequestFilter(auth.value()));
}
}
@Priority(Priorities.AUTHORIZATION)
private static class AuthorizationRequestFilter implements ContainerRequestFilter {
private final String[] roles;
AuthorizationRequestFilter() {
this.roles = null;
}
AuthorizationRequestFilter(final String[] roles) {
this.roles = roles;
}
@Override
public void filter(final ContainerRequestContext requestContext) throws IOException {
if (!this.roles[0].isEmpty()) {
for (final String role : this.roles) {
if (requestContext.getSecurityContext().isUserInRole(role)) {
return;
}
}
throw new ForbiddenException(LocalizationMessages.USER_NOT_AUTHORIZED());
}
}
}
}
非常感谢@PaulSamsotha带领我找到更合适的解决方案。