ContainerRequestFilter随机给出null

时间:2017-07-27 08:25:48

标签: java spring jersey-2.0

我有一个使用JWT进行身份验证的Spring 4 + Jersey 2 Web应用程序。

我正在使用class Logger { public function writeToLogFile(){ ... } } class DoSomethingUseful { private $logger; public function __construct(Logger $logger) //php 7 optional type hinting { $this->logger = $logger; } public function actualWork() { //do work $this->logger->writeToLogFile('whatever'); } } class Application { public function setUp() { //create database connection, other stuff $this->logger = new Logger; } public function work() { $action = new DoSomethingUseful($this->logger); $action->actualWork(); } } 拦截每个来电并检查请求是否包含正确的ContainerRequestFilter令牌:

Authorization

然后我有一个import java.util.Map; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.ext.Provider; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.auth0.jwt.JWT; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import my.beans.User; @Provider public class JWTFilter implements ContainerRequestFilter { private static final Logger LOG = LogManager.getLogger(JWTFilter.class); @Override public void filter(ContainerRequestContext context) { LOG.debug("JWT Filter"); String authorization = context.getHeaderString("Authorization"); if(authorization != null) { String jwtToken = authorization.replaceAll(".*Bearer\\s+", ""); DecodedJWT jwt = JWT.decode(jwtToken); Map<String, Claim> claims = jwt.getClaims(); String userid = claims.get("userid").asString(); if(userid != null) { User user = loadUser(userid); // save user to request, so that it gets context.setProperty("loggedUser", user); LOG.debug("User found: " + user); } } else { LOG.debug("JWT missing"); } } private User loadUser(String userid) { // loads a User object } } 类,其中BaseResource方法可以从getLoggedUser()检索数据:

ContainerRequestContext

所有泽西岛资源都扩展了import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.core.Context; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import my.beans.User; public class BaseResource { private static final Logger LOG = LogManager.getLogger(BaseResource.class); @Context private ContainerRequestContext context; public User getLoggedUser() { User u = (User) context.getProperty("loggedUser"); LOG.debug("getLoggedUser(): " + u); return u; } } 类。

这是我拥有的资源之一:

BaseResource

如果我尝试执行此资源,我会收到此日志:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import my.beans.User;

@Component
@Path("/test")
public class TestResource extends BaseResource {

    @GET
    @Produces(MediaType.APPLICATION_JSON_VALUE)
    @Path("/")
    public Response test() {
        User u = getLoggedUser();

        return Response.ok().build();
    }
}

似乎有效。

如果我一次又一次地重新刷新页面,就会发生这种情况:

DEBUG: JWT Filter
DEBUG: User found: my.beans.User@4e7fb700
DEBUG: getLoggedUser(): my.beans.User@4e7fb700

第三次,DEBUG: JWT Filter DEBUG: User found: my.beans.User@4c0bea44 DEBUG: getLoggedUser(): my.beans.User@4c0bea44 DEBUG: JWT Filter DEBUG: User found: my.beans.User@6ac29f24 DEBUG: getLoggedUser(): my.beans.User@6ac29f24 DEBUG: JWT Filter DEBUG: User found: my.beans.User@668b07db DEBUG: getLoggedUser(): null DEBUG: JWT Filter DEBUG: User found: my.beans.User@42fc180c DEBUG: getLoggedUser(): my.beans.User@42fc180c 类中的用户被找到,但控制器内有JWTFilter。这很奇怪,因为过滤器将它放在null内,所以问题不应该发生。似乎有时ContainerRequestContext无法保存数据,或者在到达控制器时丢失数据。

这里发生了什么?在调用ContainerRequestContext时,为什么要随机获取null个对象?我可以这样做吗?

值得一提的是我的过滤器是ContainerRequestContest#getProperty。我应该使用javax.ws.rs.container.ContainerRequestFilter吗?

1 个答案:

答案 0 :(得分:0)

如果要从过滤器到资源获取数据,请尝试在过滤器类中设置http标头,以便可以使用标头参数进入资源类