我有一个使用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
吗?
答案 0 :(得分:0)
如果要从过滤器到资源获取数据,请尝试在过滤器类中设置http标头,以便可以使用标头参数进入资源类