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