How do I get the @RolesAllowed annotation to work for my Web application?

前端 未结 4 473
暗喜
暗喜 2020-12-14 18:46

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

相关标签:
4条回答
  • 2020-12-14 19:05

    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.

    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.

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

    0 讨论(0)
  • 2020-12-14 19:09

    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.

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

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

    0 讨论(0)
  • 2020-12-14 19:16

    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.

    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.

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

    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:

    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:

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

    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.

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

    0 讨论(0)
  • 2020-12-14 19:18

    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.

    0 讨论(0)
提交回复
热议问题