Подтвердить что ты не робот

Как заставить аннотацию @RolesAllowed работать для моего веб-приложения?

Я делаю веб-приложение с использованием 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.

Я (относительно) новичок в веб-разработке, и поэтому я только начал понимать множество базовых концепций и технологий. Я пытаюсь создать систему разрешений с пользователями и ролями в веб-приложении, но я не могу заставить аннотацию @RolesAllowed работать в моей веб-службе RESTful. Я уже работаю над этой проблемой в течение нескольких дней.

У меня есть ресурс RESTful (Java Enterprise/Session Bean?), называемый UserResource.java, здесь у меня есть метод 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();
        }
    }
}

Этот метод создания работает, если я использую аннотацию @PermitAll, но с ошибкой не получается, если я использую аннотацию @RolesAllowed.

У меня есть представление Backbone CreateUserView, которое предоставляет форму (в HTML) конечному пользователю (с правами администратора) для создания новых пользователей для приложения. При нажатии кнопки "Отправить" данные JSON отправляются на адрес "rest/user/create" для создания нового пользователя. Прежде чем будет создан метод create в UserResource.java, моя SecurityInterceptor.java(которая реализует javax.ws.rs.container.ContainerRequestFilter) проверяет, имеет ли пользователь требуемые разрешения. Я отлаживал это обстоятельство, и Security Interceptor работает так, как должен. Поэтому после того, как Security Interceptor дает свободный доступ, в UserResource.java что-то не так. (Как примечание, не уверен, что это важно, но я считаю, что перехватчик безопасности основан на этом сообщении в блоге о безопасности RESTEasy. работал над приложением с другим парнем, он сначала реализовал его, поэтому я не уверен... но он выглядит почти идентичным. В любом случае этот парень перешел к другому проекту несколько недель назад.)

Ошибка, которую я получаю (вывод с сервера), следующая:

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 character limit on questions..)

Я видел, как другие люди задают похожие вопросы, некоторые из которых остаются без ответа по сей день (например, jax-rs service RolesAllowed Annotation throwing exception) и другие, у которых есть решения это либо не работает для меня, либо, может быть, я не применяю решение правильно (например, поддержка RESTEasy для JAX-RS @RolesAllowed).

Я нашел это: https://developer.jboss.org/thread/177728?start=0&tstart=0 (под заголовком: "@RolesAllowed, @DenyAll требует наличия org.jboss.ejb3.nnation. SecurityDomain?" ), В пробовал решение, но я не могу заставить его работать для моего проекта. Не уверен, что решение не применимо для моей ситуации или если я просто делаю это неправильно.

Я нашел это: https://developer.jboss.org/message/720815 (озаглавленный: "это дефект для обработки org.jboss.ejb3.annotation.SecurityDomain?" ), но я не понимаю, где должны быть мои jboss-ejb-client.properties. Я думаю, что они поставили свой проект совсем по-другому. Так что не повезло с этим.

Я нашел руководство по безопасности EJB3, как было предложено там, я предоставил следующий код в файле standalone.xml:

<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>

Но это ничего не решило. Я не уверен, что он что-то сделал.

Наконец, я нашел этот вопрос SO: поддержка RESTEasy для JAX-RS @RolesAllowed (которая ссылается на Документация RESTEasy). Хотя я также упомянул об этом вопросе несколько абзацев, содержащих решение, которое не работает для меня, оно изменило ошибку на другую ошибку. Как было предложено там, я добавил элемент < context-param > -block в свой файл web.xml:

<?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>

В результате возникает следующая ошибка, если я пытаюсь создать нового пользователя (не полностью размещенного здесь из-за ограничения персонажа вопросов 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.

Эта ошибка также не очень полезна, по сути, я нахожу еще меньше информации при поиске этой ошибки, чем при поиске предыдущей ошибки. Поэтому я не уверен, что это шаг в правильном направлении. Что лучше вернуть с сервера? Состояние 500 (Внутренняя ошибка сервера) или состояние 403 (Запрещено)? Кроме того, если после применения этого "решения" я изменяю аннотацию на @PermitAll, то создание нового пользователя работает так же, как и раньше, поэтому ситуация на самом деле не ухудшила ситуацию.

Однако я могу найти исходный код RoleBasedSecurityFilter, который показывает, что он выбрасывает ForbiddenException. Это показывает, что определенный метод isUserInRole должен возвращать true, но это не делает это в моем приложении. Я не могу заставить его вернуться к истине. Это заставляет меня задаться вопросом, Можно ли отключить RoleBasedSecurityFilter.java из RESTEasy?

Я также нашел следующий вопрос SO: @RolesAllowed не может быть разрешен с помощью Джерси, на который ответил Абхижит Саркар, и он ссылается на статья IBM. Возможно, решение моей проблемы лежит там, но я еще не нашел его. Во всяком случае, там предлагается добавить либо блок безопасности-роли в мой файл web.xml, либо добавить аннотацию @DeclareRoles к моему UserResource. java файл должен решить проблему, но предупреждение HTTP 403 Forbidden по-прежнему сохраняется после того, как я это сделаю. Это очень расстраивает.

Мой блок роли безопасности (в web.xml) выглядит следующим образом:

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

И я добавил следующий блок ограничений безопасности (в web.xml): (обратите внимание на ограничение auth)

<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>

Теперь я понимаю, что моя проблема заключается либо в дескрипторах развертывания (web.xml), либо в конфигурации сервера (WildFly standalone-full.xml).

Я добавил элемент login-configпроверка подлинности) в мой файл web.xml. Изменена моя страница входа в систему, чтобы соответствовать необходимый формат. Я выполнил некоторые шаги этой статьи на переносе приложения Java EE из GlassFish в WildFly, но я думаю, что все еще сделал что-то неправильно, потому что я всегда приходите на страницу ошибки входа при попытке войти в систему с действительными учетными данными пользователя.

См. здесь элемент security-domain, добавленный в мою конфигурацию 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>

Я думаю, что что-то не так с моими определенными там функциямиQuery, но я не могу понять, что.

Мне бы очень хотелось знать, как реализовать защиту на основе ролей для моего веб-приложения. Поэтому я также принимаю другие подходы к обеспечению безопасности на основе ролей, если это работает. Предложения приветствуются.

Я также разместил мой вопрос на developer.jboss.org, но я еще не получил ответа.

Я предоставил одно решение для решения моей проблемы как ответ на этот вопрос, но это не настоящее решение (как объясняется в этом ответе). Я все еще заинтересован в том, чтобы сделать это правильно.

4b9b3361

Ответ 1

Просто такая же проблема.

Это аннотация @Stateless. Маркирует ваш класс как EJB, и контейнер пытается обеспечить безопасность EJB.

Я обнаружил это, написав фильтры и свой собственный SecurityContext, только чтобы найти, что мой SecurityContext никогда не ссылался.

Удаление @Stateless привело к вызову getUserPrincipal() в SecurityContext.

Ответ 2

Основываясь на ошибке "403", мне кажется, что что-то не так с вашим запросом роли. Возможно, ваш модуль входа не назначает роль администратора для вашего пользователя. Единственное, что вы можете сделать, это реализовать механизм аутентификации http://undertow.io/undertow-docs/undertow-docs-1.3.0/#authentication-mechanisms (пример: https://github.com/dstraub/spnego-wildfly) и изменить его таким образом, чтобы вы могли проверять, какие роли ваш модуль входа назначает вашему пользователю. Внедрение механизма пользовательской аутентификации займет у вас некоторое время, но это поможет вам лучше понять, как безопасность работает в wildfly.

Другим моментом, который я должен был сделать для аннотации Roles, является изменение standalone.xml и установка вашего домена безопасности как стандартного.

Кроме того, добавление этих строк является шагом в правильном направлении, как и для меня. Без этих строк аннотации @RolesAllowed не работают для меня.

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

Кроме того, я бы советовал внедрять безопасность, используя только web.xml, и только после этого попробуйте добавить @RolesAllowed.

Ответ 3

Я нашел одно решение для своей проблемы. Однако это решение не столько для решения проблемы, сколько для workaround, потому что оно не использует аннотацию @RolesAllowed.

Поскольку я не смог понять, как точно определить дескрипторы развертывания и конфигурацию сервера, я решил, что проблема будет решена намного проще, если я просто не буду использовать аннотацию @RolesAllowed.

Даже если другие люди действительно захотят использовать элемент login-config в своем файле web.xml и не использовать другие средства аутентификации, этот подход не использует этот элемент, но вместо этого выполняет аутентификацию только через RESTful Web Services (это означает, что в дескрипторах развертывания или конфигурации сервера ничего не нужно изменять).

Я создал новую Enterprise Java Bean (EJB) под названием SecurityFilter, которая проверяет, имеет ли пользователь требуемые роли для определенных функций. Он реализуется следующим образом:

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
    }
}

Метод isUserAllowed вызывается в методе create UserResource.java. Старую реализацию этого метода создания можно увидеть в вопросе выше. Новая реализация выглядит следующим образом:

@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();
}

Как вы можете видеть, оператор if-else заменяет аннотацию @RolesAllowed в этом подходе, а мой фильтр безопасности несколько отличается.

Кроме того, этот подход использует HttpHeaders для получения заголовков запросов (в которых хранятся идентификатор пользователя и токен). Принятый ответ на вопрос SO "как получить заголовок "Принимать" на стороне сервера веб-сервиса REST" помог мне найти как получить заголовки запросов.

Кроме того, этот подход работает, не меняя ничего на моих веб-страницах Backbone.js и Bootstrap (т.е. мои файлы HTML и JavaScript).

Ответ 4

Я видел ваше сообщение в своем ответе здесь. Я не очень хорошо знаком с защитой JBoss, и я не рекомендую встроить ее в код, но я думаю, что это не моя проблема. Из вашего кода я не вижу security-role или @DeclareRoles present; в моем ответе четко сказано, что вам нужно либо одно для безопасности на основе аннотаций работать. Вы исключали это для краткости или вы пропустили его? В случае более позднего, добавьте @DeclareRoles в UserResource класс и посмотрите, поможет ли это.