Java 如何让 @RolesAllowed 注释适用于我的 Web 应用程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25851374/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I get the @RolesAllowed annotation to work for my Web application?
提问by PJvG
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.
我正在使用 Backbone.js、Bootstrap、NetBeans IDE 8.0、Java EE 7、JDK 8、WildFly 服务器 8.1.0、JBoss RESTEasy (resteasy-jaxrs-3.0.8)、JBoss 2.2.22、JBoss EJB 3 制作 Web 应用程序.
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 annotationto 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 createto create a new user for the application:
我有一个名为UserResource.java的 RESTful 资源(Java Enterprise/Session Bean?),在这里我有一个方法create来为应用程序创建一个新用户:
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 createmethod works if I use the @PermitAll annotation, but it fails with an error if I use the @RolesAllowed annotation.
如果我使用 @PermitAll 注释,这个create方法有效,但如果我使用 @RolesAllowed 注释,它会失败并显示错误。
I have this Backbone view CreateUserViewwhich 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 createmethod in UserResource.javagets 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.)
我有这个 Backbone 视图CreateUserView,它为最终用户(具有管理员权限)提供了一个表单(HTML 格式),用于为应用程序创建新用户。单击提交按钮后,JSON 数据将发送到 url 'rest/user/create' 以创建新用户。在UserResource.java 中的create方法被执行之前,我的SecurityInterceptor.java(它实现了javax.ws.rs.container.ContainerRequestFilter)检查用户是否具有所需的权限。我已经对此进行了彻底的调试,并且安全拦截器正在正常运行。所以在安全拦截器给出明确的访问权限后,UserResource.java出现问题. (作为旁注,不确定这是否重要,但我相信安全拦截器基于这篇关于 RESTEasy security 的博客文章。我正在和另一个人一起开发应用程序,他最初实现了它,所以我不确定.. 但它看起来几乎一模一样。反正那个人几周前已经转移到另一个项目了。)
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.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.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<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>
0(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.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.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<?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>
0(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.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.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.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 service RolesAllowed Annotation throwing exception),而其他人的解决方案要么对我不起作用,要么我没有正确应用解决方案(例如RESTEasy 支持 JAX-RS @RolesAllowed)。
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.propertiesare 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.SecurityDomain 的缺陷吗?”),但我不明白我的jboss-ejb在哪里-client.properties应该是。我认为他们的项目设置与我完全不同。所以没有运气。
I found a guide on EJB3 security, as suggested there, I provided the following code in my standalone.xml-file:
我找到了关于 EJB3 security 的指南,正如那里所建议的,我在我的standalone.xml文件中提供了以下代码:
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.
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:
最后,我发现了这个问题:RESTEasy support for JAX-RS @RolesAllowed(引用了RESTEasy 文档)。尽管我还在前面几段提到了这个问题,因为它包含一个对我不起作用的解决方案,但它确实将错误更改为另一个错误。按照那里的建议,我在web.xml文件中添加了一个<context-param>-block :
<security-role id="role_admin">
<description>This is role 1 (admin)</description>
<role-name>admin</role-name>
</security-role>
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 问题的字符限制,此处未完全发布):
<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>
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 isUserInRolemethod 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 的源代码,它表明它抛出ForbiddenException
. 它表明某个isUserInRole方法必须返回 true,但它在我的应用程序中没有这样做。我无法让它返回 true。这让我想知道,是否可以禁用 RESTEasy 的 RoleBasedSecurityFilter.java?
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-roleblock to my web.xml-file or adding a @DeclareRolesannotation to my UserResource.javafile should solve the problem, but the HTTP 403 Forbidden warning still remains after I do so. It is very frustrating.
我还发现了以下 SO 问题:@RolesAllowed 无法用 Jersey 解决,Abhijit Sarkar 对此进行了回答,他参考了一篇 IBM 文章。也许我的问题的解决方案就在那里,但我还没有找到。无论如何,建议在我的web.xml文件中添加一个安全角色块,或者向我的UserResource添加一个@DeclareRoles注释。 java文件应该可以解决问题,但是执行此操作后 HTTP 403 Forbidden 警告仍然存在。这是非常令人沮丧的。
My security-roleblock (in web.xml) looks as follows:
我的安全角色块(在 web.xml 中)如下所示:
<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>
And I added the following security-constraintblock (in web.xml): (note the auth-constraint)
我添加了以下安全约束块(在 web.xml 中):(注意auth-constraint)
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
}
}
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 的standalone-full.xml)。
I added a login-config
element (with FORM authentication) to my web.xmlfile. 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文件中添加了一个login-config
元素(带有FORM 身份验证)。更改了我的登录 HTML 页面以适合所需的格式。我遵循了本文关于将 Java EE 应用程序从 GlassFish 迁移到 WildFly 的一些步骤,但我认为我仍然做错了一些事情,因为在尝试使用有效的用户凭据登录时总是出现登录错误页面。
See here the security-domain
element I added to my WildFly configuration:
在此处查看security-domain
我添加到 WildFly 配置中的元素:
@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();
}
I think something is wrong with my rolesQuerydefined 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.
我为我的问题提供了一种解决方法作为这个问题的答案,但这不是一个真正的解决方案(如该答案中所述)。我仍然有兴趣以正确的方式做到这一点。
采纳答案by tptptp
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
.
删除@Stateless
导致getUserPrincipal()
被调用SecurityContext
。
回答by Abhijit Sarkar
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 专有安全不是很熟悉,我也不建议将它嵌入到代码中,但我想这不是我的问题。从你的代码中,我没有看到security-role
或@DeclareRoles
呈现;我的回答中明确提到您需要其中任何一个才能使基于注释的安全性工作。你是为了简洁而排除了它还是你错过了它?如果是后者,请添加@DeclareRoles
到UserResource
课程中,看看是否有帮助。
回答by PJvG
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 @RolesAllowedannotation.
我找到了一种解决我的问题的方法。但是,这并不是解决问题的方法workaround
,因为它没有使用@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 @RolesAllowedannotation.
由于我无法弄清楚如何准确定义我的部署描述符和服务器配置,我认为如果我不使用@RolesAllowed注释,问题会更容易解决。
Even though other people might really want to use the login-config
element in their web.xmlfile 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).
尽管其他人可能真的想login-config
在他们的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:
我创建了一个新的Enterprise Java Bean(EJB)称为SecurityFilter
该用户是否具有某些功能所需的角色检查。它的实现如下:
<context-param>
<param-name>resteasy.role.based.security</param-name>
<param-value>true</param-value>
</context-param>
The method isUserAllowedis called in the createmethod of UserResource.java. The old implementation of this createmethod can be seen in the question above. The new implementation is as follows:
在UserResource.java的create方法中调用方法isUserAllowed。这个create方法的旧实现可以在上面的问题中看到。新的实现如下:
##代码##As you can see, an if-else statement replaces the @RolesAllowedannotation in this approach and my security filter is implemented slightly different.
如您所见,if-else 语句替换了这种方法中的@RolesAllowed注释,并且我的安全过滤器的实现略有不同。
Also, this approach uses HttpHeadersto get the request headers (in which the user ID and token are stored). The accepted answeron the SO question "how to received "Accept" header in REST web service server side" helped me find how to get the request headers.
此外,此方法使用HttpHeaders来获取请求标头(其中存储了用户 ID 和令牌)。SO 问题“如何在 REST Web 服务服务器端接收“接受”标头”的公认答案帮助我找到了如何获取请求标头。
Furthermore, this approach works without changing anything in my Backbone.js- and Bootstrap-based web pages (i.e. my HTML and JavaScript files).
此外,这种方法无需更改基于Backbone.js和Bootstrap的网页(即我的 HTML 和 JavaScript 文件)中的任何内容。
回答by Zhenya
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”,我认为您的角色查询有问题。也许,您的登录模块没有为您的用户分配“管理员”角色。您可以做的一件事是实现自定义身份验证机制http://undertow.io/undertow-docs/undertow-docs-1.3.0/#authentication-mechanisms(例如: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.
为了使我的角色注释工作,我必须做的另一件事是修改 standalone.xml 并将您的安全域设置为默认域。
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 对我不起作用。
##代码##Also, I would advice implementing security using web.xml only, and only after that is done, try adding @RolesAllowed.
此外,我建议仅使用 web.xml 实现安全性,并且只有在完成后,才尝试添加 @RolesAllowed。