java - 如何访问 Web api 方法内的资源过滤器中生成的对象

标签 java jersey

我有一个 Web 方法,在查询字符串中有一个 token ,每个方法都使用此 token 来识别请求用户。

为此,我创建了一个名为 AuthenticationFilter 的 ResourceFilter,它从请求中获取 token 并从数据库中检索用户信息,如果用户有效,则允许执行该方法,否则将引发 UNAUTHORIZED 异常。

我的问题是:我如何访问在 AuthenticationFilter 类中检索到的用户信息

我的网络 API:

@GET
@Consumes(MediaType.TEXT_PLAIN)
@Produces({MediaType.APPLICATION_JSON})
@Path("/getUserOrders")
@ResourceFilters({AuthenticationFilter.class, AllowOroginFilter.class})
public String getUserOrders(@Context UriInfo uriInfo) {
    //I need to access Usr object that retrived in AuthenticationFilter
    /*User Usr = AuthenticationFilter.Usr;*/
    String Result = getUserOrders(Usr);
    return Result;
}

资源过滤器代码:

public class AuthenticationFilter implements ResourceFilter, ContainerRequestFilter, ContainerResponseFilter {
        public User usr = null;
        @Override
        public ContainerRequest filter(ContainerRequest containerRequest) {
            usr = AuthenticationUtiity.AuthenticateRequest(containerRequest);
            if(usr == null){
                Response.ResponseBuilder builder = null;
                String response = "{\"Success\":false, \"Message\":\"Invalid username or password\"}";
                builder = Response.status(Response.Status.UNAUTHORIZED).entity(response);
                throw new WebApplicationException(builder.build());
            }
            return containerRequest;
        }
    }

我用谷歌搜索了这个问题,找到了一种方法可以使用 ThreadLocal 并将用户保存到 ThreadLocal 中并在该线程中的任何位置获取它。

https://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/

有没有更简单的方法来做到这一点?谢谢

最佳答案

您可以设置 SecurityContextContainerRequest上。然后在您的资源方法中,您可以使用 @Context SecurityContext 注入(inject)它。对于 SecurityContext 实现,您可以实现 Principal 并根据需要使其详细。当您在资源方法中获取 Principal 时,只需将其转换为您的类型即可。下面是一个过滤器示例:

@Provider
public class TestFilter implements ContainerRequestFilter {

    @Override
    public ContainerRequest filter(ContainerRequest request) {
        SecurityContext oldSec = request.getSecurityContext();

        final String username = "foobar";
        final String email = "email@email.com";
        final User user = new User(username, email);

        request.setSecurityContext(new MySecurityContext(user, oldSec.isSecure()));
        return request;
    }

    private static class MySecurityContext implements SecurityContext {

        private final boolean isSecure;
        private final User user;

        public MySecurityContext(User user, boolean isSecure) {
            this.isSecure = isSecure;
            this.user = user;
        }

        @Override
        public Principal getUserPrincipal() {
            return this.user;
        }

        @Override
        public boolean isUserInRole(String s) {
            return false;
        }

        @Override
        public boolean isSecure() {
            return this.isSecure;
        }

        @Override
        public String getAuthenticationScheme() {
            return null;
        }
    }

    public static class User implements Principal {

        private final String email;
        private final String username;

        public User(String username, String email) {
            this.username = username;
            this.email = email;
        }

        @Override
        public String getName() {
            return null;
        }

        public String getEmail() {
            return this.email;
        }
    }
}

然后在资源方法中

@Path("test")
public class TestResource {

    @GET
    public String get(@Context SecurityContext sc) {
        TestFilter.User user = (TestFilter.User) sc.getUserPrincipal();
        return user.getEmail();
    }
}

更新

thank you for the answer but i dont want to add extra argument to my web method

然后将其作为字段注入(inject)

@Path("test")
public class TestResource {

    @Context
    private SecurityContext sc;

    @GET
    public String get() {
        TestFilter.User user = (TestFilter.User) sc.getUserPrincipal();
        return user.getEmail();
    }
}

关于java - 如何访问 Web api 方法内的资源过滤器中生成的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51582999/

相关文章:

java - 让我的矩形随机从我的屏幕上掉下来?

java - 从与类路径不同的位置加载 spring XML

java - 在 Android 中将 PullToRefresh 与 UITableView 结合使用

java - 如何在 web.xml 中过滤除请求应用程序引擎开发控制台之外的所有内容

java - 使用 DropWizard 对 JAX-RS 端点执行单元测试时无法挂起异步请求的连接

java - 日期解析给出错误的值

java - 如何将字符串拆分为列

java - 有没有办法配置 Jersey 客户端请求日志记录的级别?

java - Jersey @Path 注释在类级别是必需的

java - 如何使用 log4j 查看 Jersey