我不确定这是否可行,但是我正在尝试设置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
相关课程:
ApplicationConfig.java
@ApplicationPath("rest")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
packages("rest");
register(RolesAllowedDynamicFeature.class);
}
}
TestSBFacade.java
@Local
public interface TestSBFacade {
public List<Test> findAll();
}
TestSB.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();
}
}
AuthFilter.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实现,它们不能很好地结合在一起。因此,我决定创建自己的注释,并在ApplicationConfig.java
中注册我自己的DynamicFeature。
授权.java
@Documented
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Authorized {
public String[] value() default "";
}
AuthorizationDynamicFeature.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将我引向一个更合适的解决方案。