java - Jax-RS 过滤器将对象传递给资源

标签 java jax-rs

我想将过滤器中用于身份验证的用户对象传递给资源。可能吗?

我使用的是 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);
  }
}

最佳答案

我认为有两种方法可以做到这一点。第一种可能是更标准的方法,但代码也更多。最终您将注入(inject)用户作为请求的一部分。但是,此解决方案首先需要的是 Principal 。一个非常简单的可能是:

import java.security.Principal;

...

public class UserPrinicipal implements Prinicipal {
  // most of your existing User class but needs to override getName()
}

然后,在您的过滤器中:

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

在您想要 User 的类中,您可以执行以下操作:

@Path("/myservice")
public class MyService {
    @Context
    private SecurityContext securityContext;

    @Path("/something")
    @GET
    public Response getSomething() {
        User user = (User)securityContext.getUserPrincipal();
    }
}

我已经按照这种方式实现了它并且效果很好。然而,一种可以说更简单的方法是将用户存储在 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);

然后,为您服务:

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

第二种方法的缺点是,您实际上不再是无状态服务,因为您将状态存储在某处。但即使您不使用 HttpSession,它仍然存在。

关于java - Jax-RS 过滤器将对象传递给资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45381946/

相关文章:

java - 比较多个字符串时切换大小写与 If, else

java - 为什么 Collections 参数中的 unmodifiableList 是 <?延伸 T>

java - 如何定义一个没有定义长度的数组

java - REST Web 服务/Web UI 服务的单独异常映射

java - 将 google appengine datastore.key 与 REST 结合使用时出错

java - 如何让 Jersey 2/Spring 4 在没有 web.xml 配置的情况下从 @Configuration 加载 beans

java - GeoTools,加载 map 时出错

java - 使用 Jax-Rs 上的注释 Post 发送和不发送文件

java - 将 JaxRS REST 服务与 WebSocket 集成

java - Mongodb文档格式一致性