如何让Jersey @Roles允许@Stateless工作?

时间:2018-09-03 21:32:28

标签: java jax-rs jersey-2.0 ejb-3.1

我不确定这是否可行,但是我正在尝试设置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语句中。非常感谢您的帮助和见解。

1 个答案:

答案 0 :(得分:1)

因此,显然由于使用@RolesAllowed的EJB和JAX-RS实现,它们不能很好地结合在一起。因此,我决定创建自己的注释,并在ApplicationConfig.java中注册自己的DynamicFeature。

Authorized.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为我提供了更合适的解决方案。