如何让@RolesAllowed注释在Web应用程序中工作?

时间:2022-06-12 02:31:13

I am making a Web application using Backbone.js, Bootstrap, NetBeans IDE 8.0, Java EE 7, JDK 8, WildFly server 8.1.0, JBoss RESTEasy (resteasy-jaxrs-3.0.8), JBoss 2.2.22, JBoss EJB 3.

我正在使用主干构建一个Web应用程序。Java EE 7, JDK 8, WildFly服务器8.1.0,JBoss RESTEasy (reste -jaxrs-3.0.8), JBoss 2.2.22, JBoss EJB 3。

I am (relatively) new to Web development, and as such I have only just started to grasp a lot of basic concepts and technologies. I am trying to build a permission system with users and roles into a Web application, but I cannot seem to make the @RolesAllowed annotation to work in my RESTful Web Service. I am already working on this problem for a few days.

我对Web开发(相对而言)比较陌生,因此我才刚刚开始掌握许多基本的概念和技术。我试图在Web应用程序中构建一个具有用户和角色的权限系统,但是我似乎无法使@RolesAllowed注释在我的RESTful Web服务中工作。我已经研究这个问题几天了。

I have a RESTful resource (Java Enterprise/Session Bean?) called UserResource.java, in here I have a method create to create a new user for the application:

我有一个名为UserResource的RESTful资源(Java Enterprise/Session Bean?)java,在这里我有一个为应用程序创建新用户的方法:

import java.net.URI;
import java.security.Principal;
import java.util.List;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import org.jboss.ejb3.annotation.SecurityDomain;

@Stateless
@SecurityDomain("other")
@Path("/user")
public class UserResource {
    @EJB(name = "UserServiceImp")
    UserService userService;

    @Context
    private UriInfo uriInfo;

    @RolesAllowed({"admin"})
    @Path("create")
    @POST
    public Response create(CreateRequest request) {        
        try {
            System.out.println("Start of create method");
            User user = userService.createUser(request);
            return getCreateResponse(user);
        }
        catch (Exception e){
            return Response.status(401).entity("Failed to create user").build();
        }
    }
}

This create method works if I use the @PermitAll annotation, but it fails with an error if I use the @RolesAllowed annotation.

如果我使用@PermitAll注释,这个创建方法就可以工作,但是如果我使用@RolesAllowed注释,它就会出错。

I have this Backbone view CreateUserView which provides a form (in HTML) to an end user (with admin rights) for creating new users for the application. On clicking the submit button, JSON data gets send to the url 'rest/user/create' for creating a new user. Before the create method in UserResource.java gets executed, my SecurityInterceptor.java (which implements javax.ws.rs.container.ContainerRequestFilter) checks if the user has the required permissions. I have debugged this thorough and the Security Interceptor is functioning as it should. So after the Security Interceptor gives clear access, something goes wrong in UserResource.java. (As a side note, not sure if this is important, but I believe the Security Interceptor is based on this blog post about RESTEasy security. I was working on the application with another guy, he initially implemented it, so I'm not sure.. but it looks almost identical. Anyway that guy has moved on to another project a few weeks ago.)

我有这个主干视图CreateUserView,它为终端用户(具有管理权限)提供了一个表单,用于为应用程序创建新用户。在单击submit按钮时,JSON数据被发送到用于创建新用户的url“rest/user/create”。在UserResource中的create方法之前。java被执行,我的SecurityInterceptor。java(实现了java .ws.r .container. containerrequestfilter)检查用户是否具有所需的权限。我已经调试过了,安全拦截器正在正常工作。所以在安全拦截器提供清晰访问之后,UserResource.java出现了问题。(顺便说一句,我不确定这是否重要,但我相信安全拦截器是基于这篇关于RESTEasy安全性的博文。我和另一个人一起做这个应用,他最初实现了它,所以我不确定。但它看起来几乎是一样的。不管怎么说,那家伙几个星期前又换了一个项目。

The error I am getting (output from the server) is the following:

我得到的错误(从服务器输出)如下:

16:45:25,775 ERROR [org.jboss.as.ejb3.invocation] (default task-60) JBAS014134: EJB Invocation failed on component UserResource for method public javax.ws.rs.core.Response org.profit.pgb.rest.resource.UserResource.create(org.profit.pgb.rest.api.CreateRequest): javax.ejb.EJBAccessException: JBAS014502: Invocation on method: public javax.ws.rs.core.Response org.profit.pgb.rest.resource.UserResource.create(org.profit.pgb.rest.api.CreateRequest) of bean: UserResource is not allowed
    at org.jboss.as.ejb3.security.AuthorizationInterceptor.processInvocation(AuthorizationInterceptor.java:135) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:95) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:59) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:55) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:326)
    at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:448)
    at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:61)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:326)
    at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
    at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:185)
    at org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:182)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
    at org.jboss.as.ee.component.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:73)
    at org.profit.pgb.rest.resource.UserResource$$$view45.create(Unknown Source) [classes:]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.8.0_11]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [rt.jar:1.8.0_11]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.8.0_11]
    at java.lang.reflect.Method.invoke(Method.java:483) [rt.jar:1.8.0_11]
    at org.jboss.weld.util.reflection.Reflections.invokeAndUnwrap(Reflections.java:401) [weld-core-impl-2.1.2.Final.jar:2014-01-09 09:23]
    at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:99) [weld-core-impl-2.1.2.Final.jar:2014-01-09 09:23]
    at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56) [weld-core-impl-2.1.2.Final.jar:2014-01-09 09:23]
    at org.jboss.weld.bean.proxy.InjectionPointPropagatingEnterpriseTargetBeanInstance.invoke(InjectionPointPropagatingEnterpriseTargetBeanInstance.java:65) [weld-core-impl-2.1.2.Final.jar:2014-01-09 09:23]
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:100) [weld-core-impl-2.1.2.Final.jar:2014-01-09 09:23]
    at org.profit.pgb.rest.resource.UserResource$Proxy$_$$_Weld$EnterpriseProxy$.create(Unknown Source) [classes:]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.8.0_11]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [rt.jar:1.8.0_11]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.8.0_11]
    at java.lang.reflect.Method.invoke(Method.java:483) [rt.jar:1.8.0_11]
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:137) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:296) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:250) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:237) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) [resteasy-jaxrs-3.0.8.Final.jar:]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:177) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_11]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_11]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_11]

16:45:25,957 ERROR [io.undertow.request] (default task-60) UT005023: Exception handling request to /pgb/rest/user/create: org.jboss.resteasy.spi.UnhandledException: javax.ejb.EJBAccessException: JBAS014502: Invocation on method: public javax.ws.rs.core.Response org.profit.pgb.rest.resource.UserResource.create(org.profit.pgb.rest.api.CreateRequest) of bean: UserResource is not allowed
    at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:212) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:149) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:372) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) [resteasy-jaxrs-3.0.8.Final.jar:]
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) [resteasy-jaxrs-3.0.8.Final.jar:]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:177) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_11]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_11]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_11]
Caused by: javax.ejb.EJBAccessException: JBAS014502: Invocation on method: public javax.ws.rs.core.Response org.profit.pgb.rest.resource.UserResource.create(org.profit.pgb.rest.api.CreateRequest) of bean: UserResource is not allowed
    at org.jboss.as.ejb3.security.AuthorizationInterceptor.processInvocation(AuthorizationInterceptor.java:135) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:95) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
    at ... etc. (not fully shown due to SO's character limit on questions..)

I've seen other people ask similar questions, some which remain unanswered to this day (e.g. jax-rs service RolesAllowed Annotation throwing exception) and others which have solutions that either do not work for me or maybe I do not apply the solution correctly (e.g. RESTEasy support for JAX-RS @RolesAllowed).

我曾见过其他人提出类似的问题,其中一些问题至今仍未得到解答(例如jax-rs服务RolesAllowed Annotation throw exception),另一些问题的解决方案要么对我不起作用,要么可能我没有正确地应用该解决方案(例如,对jax-rs @RolesAllowed的RESTEasy支持)。

I found this: https://developer.jboss.org/thread/177728?start=0&tstart=0 (titled: "@RolesAllowed, @DenyAll require presence of org.jboss.ejb3.annotation.SecurityDomain?"), In tried the solution but I cannot get it to work for my project. Not sure if the solution is not applicable for my situation or if I'm just doing it wrong.

我发现这:https://developer.jboss.org/thread/177728?start=0&tstart=0(标题为:“@RolesAllowed, @DenyAll要求出现org.jboss.ejb3.annotation.SecurityDomain?”)不确定解决方案是否适用于我的情况,或者我只是做错了。

I found this: https://developer.jboss.org/message/720815 (titled: "is this a defect for processing org.jboss.ejb3.annotation.SecurityDomain ?"), but I do not understand where my jboss-ejb-client.properties are supposed to be. I think they set their project up quite different from me. So no luck with that.

我发现:https://developer.jboss.org/message/720815(标题为:“这是处理org.jboss.ejb3.annotation的缺陷吗?”)),但我不知道我的jboss-ejb-client在哪里。属性应该是。我认为他们的计划和我的完全不同。所以没有运气。

I found a guide on EJB3 security, as suggested there, I provided the following code in my standalone.xml-file:

我找到了一个关于EJB3安全性的指南,正如那里建议的,我在我的立场中提供了以下代码。

<security-domain name="other" cache-type="default">
    <authentication>
        <login-module code="Remoting" flag="optional">
            <module-option name="password-stacking" value="useFirstPass"/>
        </login-module>
        <login-module code="RealmDirect" flag="required">
            <module-option name="password-stacking" value="useFirstPass"/>
        </login-module>
    </authentication>
</security-domain>

But that did not solve anything at all. I am not sure if it did anything.

但这并不能解决任何问题。我不确定它是否有什么作用。

Finally, I found this SO question: RESTEasy support for JAX-RS @RolesAllowed (which references to the RESTEasy Documentation). Even though I also mentioned this question a few paragraphs up as containing a solution that does not work for me, it did change the error to another error. As suggested there I added a <context-param>-block to my web.xml-file:

最后,我发现了这个SO问题:对JAX-RS @ rolesallow的RESTEasy支持(它引用了RESTEasy文档)。尽管我在前面几段中也提到了这个问题,它包含了一个对我不起作用的解决方案,但它确实将错误变成了另一个错误。如建议的那样,我在我的web.xml文件中添加了 -block:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>PGB</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>

        <user-data-constraint>
            <!-- use of SSL is required when CONFIDENTIAL is specified -->
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <context-param>
      <param-name>resteasy.role.based.security</param-name>
      <param-value>true</param-value>
   </context-param>
</web-app>

Which results in the following error if I try to create a new user (not completely posted here due to character limit of SO questions):

如果我尝试创建一个新用户(由于SO问题的字符限制,没有完全发布在这里),将导致以下错误:

16:58:45,992 WARN  [org.jboss.resteasy.core.ExceptionHandler] (default task-61) failed to execute: javax.ws.rs.ForbiddenException: HTTP 403 Forbidden
    at org.jboss.resteasy.plugins.interceptors.RoleBasedSecurityFilter.filter(RoleBasedSecurityFilter.java:45) [resteasy-jaxrs-3.0.8.Final.jar:]
    at ... etc.

This error is not very helpful either, in fact, I find even less information when I search on that error than when I search on the previous error. So, I am not sure if that is a step into the right direction. What is better to have returned from the server? A status 500 (Internal Server Error) or a status 403 (Forbidden)? Also, if after applying that "solution" I change the annotation to @PermitAll, then the creation of a new user works just as before, so it didn't really make the situation any worse.

这个错误也不是很有用,事实上,当我搜索那个错误的时候,我发现的信息比我搜索前一个错误的时候还要少。所以,我不确定这是否是迈向正确方向的一步。从服务器返回更好的是什么?状态500(内部服务器错误)还是状态403(禁止)?另外,如果在应用了那个“解决方案”之后,我将注释改为@PermitAll,那么创建一个新用户就会像以前一样工作,所以不会使情况变得更糟。

However, I can find the source code of RoleBasedSecurityFilter, which shows that it throws the ForbiddenException. It shows that a certain isUserInRole method must return true, but it does not do that in my application. I can't get it to return true. It makes me wonder, Is it possible to disable RoleBasedSecurityFilter.java of RESTEasy?

但是,我可以找到RoleBasedSecurityFilter的源代码,它显示抛出了禁止异常。它表明某个isUserInRole方法必须返回true,但在我的应用程序中它没有这样做。我不能让它返回真。这让我很好奇,是否可以禁用RoleBasedSecurityFilter。java RESTEasy吗?

I also found the following SO question: @RolesAllowed cannot be resolved with Jersey, which is answered by Abhijit Sarkar, and he refers to an IBM article. Maybe the solution to my problem lies in there, but I have not found it yet.. Anyway, it is suggested there that either adding a security-role block to my web.xml-file or adding a @DeclareRoles annotation to my UserResource.java file should solve the problem, but the HTTP 403 Forbidden warning still remains after I do so. It is very frustrating.

我还发现了下面的SO问题:@ rolesallow不能用Jersey来解决,这个问题由Abhijit Sarkar回答,他引用了IBM的一篇文章。也许解决我问题的方法就在那里,但我还没有找到。无论如何,建议在我的web上添加一个安全角色块。xml文件或向我的UserResource添加@DeclareRoles注释。java文件应该可以解决这个问题,但是HTTP 403禁止的警告在我这么做之后仍然存在。它非常令人沮丧。

My security-role block (in web.xml) looks as follows:

我的安全角色块(在web.xml中)如下:

<security-role id="role_admin">
    <description>This is role 1 (admin)</description>
    <role-name>admin</role-name>
</security-role>

And I added the following security-constraint block (in web.xml): (note the auth-constraint)

我添加了以下安全约束块(在web.xml中):(注意验证约束)

<security-constraint>
    <web-resource-collection>
        <web-resource-name>PGB</web-resource-name>
        <url-pattern>/rest/user/create</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint id="AuthConstraint_createUser">
        <description> Only admin can create a new user</description>
        <role-name>admin</role-name>
    </auth-constraint>
    <user-data-constraint>
        <!-- use of SSL is required when CONFIDENTIAL is specified -->
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

I realize now that my problem lies either in the deployment descriptors (web.xml) or the server configuration (WildFly's standalone-full.xml).

我现在意识到我的问题在于部署描述符(web.xml)或服务器配置(WildFly的standone -full.xml)。

I added a login-config element (with FORM authentication) to my web.xml file. Changed my login HTML page to fit the required format. I followed some of the step of this article on migrating a Java EE App from GlassFish to WildFly, but I think I still did something wrong because I always get at the login error page when trying to log in with valid user credentials.

我向我的web添加了一个登录配置元素(带有表单验证)。xml文件。更改了登录HTML页面以适应所需的格式。我遵循了本文的一些步骤,将一个Java EE应用程序从GlassFish迁移到WildFly,但是我认为我仍然做了一些错误的事情,因为我总是在尝试使用有效的用户凭证登录时登录错误页面。

See here the security-domain element I added to my WildFly configuration:

请参见我在我的WildFly配置中添加的安全域元素:

<security-domain name="app" cache-type="default">
    <authentication>
        <login-module code="Database" flag="required">
            <module-option name="dsJndiName" value="java:jboss/datasources/mySQL_pool_rel"/>
            <module-option name="principalsQuery" value="select hashed_password from user where email_address=?"/>
            <module-option name="rolesQuery" value="select role_name, 'Roles' from role r inner join user u on r.role_type = u.role_type where u.email_address = ?"/>
            <module-option name="hashAlgorithm" value="SHA-256"/>
            <module-option name="hashEncoding" value="BASE64"/>
            <module-option name="unauthenticatedIdentity" value="guest"/>
        </login-module>
        <login-module code="RoleMapping" flag="required">
             <module-option name="rolesProperties" value="file:${jboss.server.config.dir}/app.properties"/>
             <module-option name="replaceRole" value="false"/>
        </login-module>
    </authentication>
</security-domain>

I think something is wrong with my rolesQuery defined there, but I can't figure out what.

我觉得我定义的rolesQuery有问题,但我不知道是什么。

I would love to know how to implement role-based security for my Web application. Therefore, I also accept other approaches to role-based security, as long as it works. Suggestions are welcome.

我想知道如何为我的Web应用程序实现基于角色的安全性。因此,我也接受其他基于角色安全的方法,只要它有效。欢迎提出您的建议。

I also placed my question on developer.jboss.org, but I also got no response there yet.

我也在developer.jboss.org上提出了我的问题,但我也没有得到任何回应。

I provided one workaround solution to my problem as an answer to this question, but it is not a real solution (as explained in that answer). I am still interested in doing this the right way.

我为我的问题提供了一个变通的解决方案作为这个问题的答案,但是它不是一个真正的解决方案(正如在那个答案中解释的那样)。我仍然对用正确的方式做这件事感兴趣。

4 个解决方案

#1


5  

Just had the same problem.

只是有同样的问题。

It's the @Stateless annotation. The marks your class as an EJB and the container attempts to enforce EJB security.

@Stateless注释。将类标记为EJB,容器尝试执行EJB安全性。

I discovered this by writing filters and my own SecurityContext, only to find that my SecurityContext was never referenced.

我通过编写过滤器和我自己的SecurityContext发现了这一点,结果发现我的SecurityContext从未被引用过。

Removing @Stateless resulted in getUserPrincipal() being called on the SecurityContext.

删除@无状态导致在SecurityContext上调用getUserPrincipal()。

#2


5  

Based on the error "403", it seems to me that there is something wrong with your role query. Maybe, your login module doesn't assign "admin" role to your user. One thing you could do is implement a custom authentication mechanism http://undertow.io/undertow-docs/undertow-docs-1.3.0/#authentication-mechanisms (example: https://github.com/dstraub/spnego-wildfly), and modify it in such a way that you could check which roles your login module assigns to your user. Implementing custom authentication mechanism is going to take you some time, but it helps you understand better how security works in wildfly.

根据错误“403”,我认为您的角色查询有问题。也许,您的登录模块没有将“admin”角色分配给您的用户。您可以做的一件事是实现一个自定义的身份验证机制:http://undertow.io/undertow-docs/undertow-docs/undertow-docs-1.3.0 /#认证机制(示例:https://github.com/dstraub/spnego-wildfly),并以这样的方式修改它,您可以检查登录模块分配给您的用户的角色。实现自定义身份验证机制将花费您一些时间,但是它可以帮助您更好地理解在wildfly中安全性的工作方式。

Other thing I had to do for my Roles annotation to work is modify standalone.xml and set your security-domain as the default one.

我还需要做的另一件事,我的角色注释工作是修改独立。将您的安全域设置为默认值。

Also, adding those lines is a step in the right direction, as for me. Without those lines annotations @RolesAllowed don't work for me.

此外,对我来说,添加这些线条是朝着正确方向迈出的一步。如果没有这些行注解@RolesAllowed对我来说是行不通的。

<context-param>
    <param-name>resteasy.role.based.security</param-name>
    <param-value>true</param-value>
</context-param>

Also, I would advice implementing security using web.xml only, and only after that is done, try adding @RolesAllowed.

另外,我建议使用web实现安全性。只使用xml,在完成之后,尝试添加@RolesAllowed。

#3


1  

I found one solution to my problem. However, this isn't as much a solution to the problem as it is a workaround, because it does not use the @RolesAllowed annotation.

我找到了一个解决我问题的办法。但是,这并不是解决问题的方法,因为它是一个解决方案,因为它不使用@RolesAllowed注释。

Since I was unable to figure out how to define my deployment descriptors and server configuration exactly, I figured the problem would be solved much easier if I simply did not use the @RolesAllowed annotation.

由于我无法确切地确定如何定义部署描述符和服务器配置,因此我认为,如果我不使用@RolesAllowed注释,问题将会更容易解决。

Even though other people might really want to use the login-config element in their web.xml file and not use any other means of authentication, this approach does not use that element but instead does authentication solely through RESTful Web Services (which means that nothing needs to change in the deployment descriptors or the server configuration).

即使其他人可能真的想在他们的web中使用登录配置元素。不使用任何其他身份验证方法的xml文件,此方法不使用该元素,而是仅通过RESTful Web服务进行身份验证(这意味着无需更改部署描述符或服务器配置)。

I created a new Enterprise Java Bean (EJB) called SecurityFilter which checks if a user has the required roles for certain functionalities. It is implemented as follows:

我创建了一个名为SecurityFilter的新企业Java Bean (EJB),它检查用户是否具有某些功能所需的角色。执行情况如下:

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ws.rs.core.HttpHeaders;
import org.profit.pgb.rest.user.UserService;

@Stateless
public class SecurityFilter
{
    @EJB(name = "UserServiceImp")
    UserService userService;

    public boolean isUserAllowed (String[] rolesArray, HttpHeaders hHeaders)
    {
        Set<String> rolesSet = new HashSet<>(Arrays.asList(rolesArray));

        String uuid = hHeaders.getRequestHeader("user").get(0);
        String token = hHeaders.getRequestHeader("token").get(0);

        if (userService.isAuthorizationTokenValid(uuid, token))
        {
           if (userService.isUserAllowed(uuid, rolesSet))
           {
               return true; // user allowed access
           }
        }   
        return false; // 401
    }
}

The method isUserAllowed is called in the create method of UserResource.java. The old implementation of this create method can be seen in the question above. The new implementation is as follows:

在UserResource.java的create方法中调用isUserAllowed方法。这个create方法的旧实现可以在上面的问题中看到。新的执行情况如下:

@PermitAll
@Path("create")
@POST
public Response create(CreateRequest request, @Context HttpHeaders hHeaders) {  
    if (securityFilter.isUserAllowed(new String[]{"admin"}, hHeaders))
    {
        try {
            System.out.println("Start of create method");
            User user = userService.createUser(request);
            return getCreateResponse(user);
        }
        catch (Exception e){
            return Response.status(401).entity("Failed to create user").build();
        }
    }
    else
        return Response.status(401).entity("Access denied! User does not have permission to create user").build();
}

As you can see, an if-else statement replaces the @RolesAllowed annotation in this approach and my security filter is implemented slightly different.

如您所见,在这种方法中,if-else语句替换了@RolesAllowed注释,我的安全过滤器实现略有不同。

Also, this approach uses HttpHeaders to get the request headers (in which the user ID and token are stored). The accepted answer on the SO question "how to received "Accept" header in REST web service server side" helped me find how to get the request headers.

另外,该方法使用httpheader获取请求标头(在其中存储用户ID和令牌)。对于SO问题“如何在REST web服务服务器端接收“Accept”报头”的公认回答帮助我找到了如何获取请求报头。

Furthermore, this approach works without changing anything in my Backbone.js- and Bootstrap-based web pages (i.e. my HTML and JavaScript files).

此外,这种方法在我的基础上没有任何改变。基于js和bootstrap的web页面(即我的HTML和JavaScript文件)。

#4


0  

I saw your post on my answer here. I'm not very familiar with JBoss proprietary security, neither do I recommend having it embedded in the code, but I guess that's not my problem. From your code, I don't see security-role or @DeclareRoles present; it is clearly mentioned in my answer that you need either one for annotation-based security to work. DId you exclude that for brevity or did you miss it? In case of the later, add @DeclareRoles to UserResource class and see if that helps.

我在这里看到你的帖子。我不太熟悉JBoss专有安全性,也不建议将它嵌入到代码中,但我想这不是我的问题。从您的代码中,我看不到安全角色或@DeclareRoles;在我的回答中明确提到,您需要任何一种基于注解的安全性来工作。你是为了简洁而把它排除在外,还是漏掉了?在后面的例子中,将@DeclareRoles添加到UserResource类中,看看这是否有帮助。

#1


5  

Just had the same problem.

只是有同样的问题。

It's the @Stateless annotation. The marks your class as an EJB and the container attempts to enforce EJB security.

@Stateless注释。将类标记为EJB,容器尝试执行EJB安全性。

I discovered this by writing filters and my own SecurityContext, only to find that my SecurityContext was never referenced.

我通过编写过滤器和我自己的SecurityContext发现了这一点,结果发现我的SecurityContext从未被引用过。

Removing @Stateless resulted in getUserPrincipal() being called on the SecurityContext.

删除@无状态导致在SecurityContext上调用getUserPrincipal()。

#2


5  

Based on the error "403", it seems to me that there is something wrong with your role query. Maybe, your login module doesn't assign "admin" role to your user. One thing you could do is implement a custom authentication mechanism http://undertow.io/undertow-docs/undertow-docs-1.3.0/#authentication-mechanisms (example: https://github.com/dstraub/spnego-wildfly), and modify it in such a way that you could check which roles your login module assigns to your user. Implementing custom authentication mechanism is going to take you some time, but it helps you understand better how security works in wildfly.

根据错误“403”,我认为您的角色查询有问题。也许,您的登录模块没有将“admin”角色分配给您的用户。您可以做的一件事是实现一个自定义的身份验证机制:http://undertow.io/undertow-docs/undertow-docs/undertow-docs-1.3.0 /#认证机制(示例:https://github.com/dstraub/spnego-wildfly),并以这样的方式修改它,您可以检查登录模块分配给您的用户的角色。实现自定义身份验证机制将花费您一些时间,但是它可以帮助您更好地理解在wildfly中安全性的工作方式。

Other thing I had to do for my Roles annotation to work is modify standalone.xml and set your security-domain as the default one.

我还需要做的另一件事,我的角色注释工作是修改独立。将您的安全域设置为默认值。

Also, adding those lines is a step in the right direction, as for me. Without those lines annotations @RolesAllowed don't work for me.

此外,对我来说,添加这些线条是朝着正确方向迈出的一步。如果没有这些行注解@RolesAllowed对我来说是行不通的。

<context-param>
    <param-name>resteasy.role.based.security</param-name>
    <param-value>true</param-value>
</context-param>

Also, I would advice implementing security using web.xml only, and only after that is done, try adding @RolesAllowed.

另外,我建议使用web实现安全性。只使用xml,在完成之后,尝试添加@RolesAllowed。

#3


1  

I found one solution to my problem. However, this isn't as much a solution to the problem as it is a workaround, because it does not use the @RolesAllowed annotation.

我找到了一个解决我问题的办法。但是,这并不是解决问题的方法,因为它是一个解决方案,因为它不使用@RolesAllowed注释。

Since I was unable to figure out how to define my deployment descriptors and server configuration exactly, I figured the problem would be solved much easier if I simply did not use the @RolesAllowed annotation.

由于我无法确切地确定如何定义部署描述符和服务器配置,因此我认为,如果我不使用@RolesAllowed注释,问题将会更容易解决。

Even though other people might really want to use the login-config element in their web.xml file and not use any other means of authentication, this approach does not use that element but instead does authentication solely through RESTful Web Services (which means that nothing needs to change in the deployment descriptors or the server configuration).

即使其他人可能真的想在他们的web中使用登录配置元素。不使用任何其他身份验证方法的xml文件,此方法不使用该元素,而是仅通过RESTful Web服务进行身份验证(这意味着无需更改部署描述符或服务器配置)。

I created a new Enterprise Java Bean (EJB) called SecurityFilter which checks if a user has the required roles for certain functionalities. It is implemented as follows:

我创建了一个名为SecurityFilter的新企业Java Bean (EJB),它检查用户是否具有某些功能所需的角色。执行情况如下:

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ws.rs.core.HttpHeaders;
import org.profit.pgb.rest.user.UserService;

@Stateless
public class SecurityFilter
{
    @EJB(name = "UserServiceImp")
    UserService userService;

    public boolean isUserAllowed (String[] rolesArray, HttpHeaders hHeaders)
    {
        Set<String> rolesSet = new HashSet<>(Arrays.asList(rolesArray));

        String uuid = hHeaders.getRequestHeader("user").get(0);
        String token = hHeaders.getRequestHeader("token").get(0);

        if (userService.isAuthorizationTokenValid(uuid, token))
        {
           if (userService.isUserAllowed(uuid, rolesSet))
           {
               return true; // user allowed access
           }
        }   
        return false; // 401
    }
}

The method isUserAllowed is called in the create method of UserResource.java. The old implementation of this create method can be seen in the question above. The new implementation is as follows:

在UserResource.java的create方法中调用isUserAllowed方法。这个create方法的旧实现可以在上面的问题中看到。新的执行情况如下:

@PermitAll
@Path("create")
@POST
public Response create(CreateRequest request, @Context HttpHeaders hHeaders) {  
    if (securityFilter.isUserAllowed(new String[]{"admin"}, hHeaders))
    {
        try {
            System.out.println("Start of create method");
            User user = userService.createUser(request);
            return getCreateResponse(user);
        }
        catch (Exception e){
            return Response.status(401).entity("Failed to create user").build();
        }
    }
    else
        return Response.status(401).entity("Access denied! User does not have permission to create user").build();
}

As you can see, an if-else statement replaces the @RolesAllowed annotation in this approach and my security filter is implemented slightly different.

如您所见,在这种方法中,if-else语句替换了@RolesAllowed注释,我的安全过滤器实现略有不同。

Also, this approach uses HttpHeaders to get the request headers (in which the user ID and token are stored). The accepted answer on the SO question "how to received "Accept" header in REST web service server side" helped me find how to get the request headers.

另外,该方法使用httpheader获取请求标头(在其中存储用户ID和令牌)。对于SO问题“如何在REST web服务服务器端接收“Accept”报头”的公认回答帮助我找到了如何获取请求报头。

Furthermore, this approach works without changing anything in my Backbone.js- and Bootstrap-based web pages (i.e. my HTML and JavaScript files).

此外,这种方法在我的基础上没有任何改变。基于js和bootstrap的web页面(即我的HTML和JavaScript文件)。

#4


0  

I saw your post on my answer here. I'm not very familiar with JBoss proprietary security, neither do I recommend having it embedded in the code, but I guess that's not my problem. From your code, I don't see security-role or @DeclareRoles present; it is clearly mentioned in my answer that you need either one for annotation-based security to work. DId you exclude that for brevity or did you miss it? In case of the later, add @DeclareRoles to UserResource class and see if that helps.

我在这里看到你的帖子。我不太熟悉JBoss专有安全性,也不建议将它嵌入到代码中,但我想这不是我的问题。从您的代码中,我看不到安全角色或@DeclareRoles;在我的回答中明确提到,您需要任何一种基于注解的安全性来工作。你是为了简洁而把它排除在外,还是漏掉了?在后面的例子中,将@DeclareRoles添加到UserResource类中,看看这是否有帮助。