Reputation: 378
I want to pass the user object I use for authentication in a filter to the resource. Is it possible?
I'm using wildfly 10 (resteasy 3)
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
@Inject
private UserDao userDao;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
logger.warn("Filter");
String uid = requestContext.getHeaderString("Authorization");
User user;
if((user = validateUser(uid)) == null) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
}
private User validateUser(String uid) {
return userDao.getById(uid);
}
}
Upvotes: 0
Views: 1917
Reputation: 17485
There are two ways I could see to do this. The first is, perhaps, the more standard way but is also more code. Ultimately you'll inject the user as part of the request. However, the first thing you need for this solution is a Principal. A very simple one might be:
import java.security.Principal;
...
public class UserPrinicipal implements Prinicipal {
// most of your existing User class but needs to override getName()
}
Then, in your filter:
...
User user;
if((user = validateUser(uid)) == null) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
requestContext.setSecurityContext(new SecurityContext() {
@Override
public Principal getUserPrincipal() {
return user;
}
@Override
public boolean isUserInRole(String role) {
// whatever works here for your environment
}
@Override
public boolean isSecure() {
return containerRequestContext.getUriInfo().getAbsolutePath().toString().startsWith("https");
}
@Override
public String getAuthenticationScheme() {
// again, whatever works
}
});
In the class where you want the User, you could do something like:
@Path("/myservice")
public class MyService {
@Context
private SecurityContext securityContext;
@Path("/something")
@GET
public Response getSomething() {
User user = (User)securityContext.getUserPrincipal();
}
}
I've implemented it this way and it works pretty well. However, an arguably simpler way is to just store the user in the session:
@Context
private HttpServletRequest request;
...
User user;
if((user = validateUser(uid)) == null) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
request.getSession().setAttribute("user", user);
Then, in your service:
@Path("/myservice")
public class MyService {
@Context
private SecurityContext securityContext;
@Path("/something")
@GET
public Response getSomething(@Context HttpServletRequest request) {
User user = (User)request.getSession().getAttribute("user");
}
}
The downside of the second method is that you are really no longer a stateless service as you're storing state somewhere. But the HttpSession is there even if you don't use it.
Upvotes: 5