Wildfly, JAAS and SecurityContext

落花浮王杯 提交于 2019-12-13 07:17:18

问题


I'm still playin with Wildfly-9.0.1.Final and JAAS (see my previous question Wildfly and JAAS login module) in a web application that use a BASIC auth-method. While my custom login module works I got some problems about authorization. I use a RESTeasy RESTFul web service with annotation to test, here is the code:

package it.bytebear.web.mongo;

import it.bytebear.web.mongo.jaas.MongoModuleCallbackHandler;
import it.bytebear.web.mongo.model.User;

import java.security.Principal;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.SecurityContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Path("/service")
Stateless
ublic class UserServices {

    private Logger log = LoggerFactory.getLogger(UserServices.class);

    @GET
    @Path("/userA")
    @RolesAllowed({ "userA" })
    public Response postUserA() {
        return Response.ok("You're user A.", MediaType.TEXT_HTML).build();
    }

    @GET
    @Path("/userB")
    @RolesAllowed({ "userB" })
    public Response postUserB() {
        return Response.ok("You're user B.", MediaType.TEXT_HTML).build();
    }

    @GET
    @Path("/userC")
    @RolesAllowed({ "userC" })
    public Response postUserC() {
        return Response.ok("You're user C.", MediaType.TEXT_HTML).build();
    }

    @POST
    @Path("/login")
    @PermitAll
    @Consumes(MediaType.APPLICATION_JSON)
    // @Consumes("application/x-authc-username-password+json")
    public Response login(User userCredentials) {
        log.info("logging in.");
        try {
            MongoModuleCallbackHandler handler = new MongoModuleCallbackHandler();
            handler.setUsername(userCredentials.getUserName());
            handler.setPassword(userCredentials.getPassword().toCharArray());
            LoginContext loginContext = new LoginContext("MongoLoginRealm", handler);
            loginContext.login();
            Subject subject = loginContext.getSubject();
            List<String> roles = new ArrayList<String>();
            for (Principal p : subject.getPrincipals()) {
                roles.add(p.getName());
            }
            String[] userCredentialsRoles = new String[roles.size()];
            roles.toArray(userCredentialsRoles);
            userCredentials.setRoles(userCredentialsRoles);
            return Response.ok().entity(userCredentials)
                    .type(MediaType.APPLICATION_JSON_TYPE).build();
        } catch (Exception e) {
            log.error("login fails.", e);
            return Response.status(Status.FORBIDDEN).entity("Not logged")
                    .type(MediaType.APPLICATION_JSON_TYPE).build();
        }
    }

    @GET
    @Path("/logout")
    @PermitAll
    public Response logout(Request req) {
        return Response.ok().build();
    }

    @POST
    @Path("/test")
    @PermitAll
    public Response test(@Context SecurityContext ctx) {
        Principal p = ctx.getUserPrincipal();
        return Response.status(Status.OK).entity(p).build();
    }
}

My login module is correctly invoked and generate a subjec with a Group named Roles containing a Principal named userA, but when I try to access .../service/userA I always get a 403 error. I use test method to check subject but ctx.getUserPrincipal() always return null. I miss how LoginModule and SecurityContext works, how SecurityContext knows about a Subject? More important: I'd like to learn more, link to resources and docs will be appreciated.

UPDATE: In my web.xml I'm using RESTEasy security:

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

Am I messing up EJB security with RESTEasy security?


回答1:


Don't implement, configure

I suggest to avoid doing all the JAAS handling programmatically. Just use the application server configuration and security subsystem will take care of all the associations for you.

RestEasy role-based security

RestEasy implements Role-based security. It has to be enabled in application's context parameter "resteasy.role.based.security" in web.xml.

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

If you don't use this parameter, then only the security constraints (in web.xml) are available for you for authorization configuration.

Example

You can take some inspiration from my sample app on GitHub used for basic security testing. There is also a Java package with REST resources.

Still not convinced?

Take a look at following code in the security subsystem implementation of WildFly:

  • SimpleSecurityManager
  • JbossAuthenticationManager extends JaasSecurityManagerBase


来源:https://stackoverflow.com/questions/33331989/wildfly-jaas-and-securitycontext

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!