Jax-RS Filter pass object to resource

痞子三分冷 提交于 2019-12-24 19:26:14

问题


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

回答1:


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.



来源:https://stackoverflow.com/questions/45381946/jax-rs-filter-pass-object-to-resource

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