我有一個Spring 4 + Jersey 2 Web應用程序,它使用JWT進行身份驗證。ContainerRequestFilter隨機給出null
我使用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
類被所有Jersey資源擴展。
這是我所擁有的資源之一:
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: [email protected]
DEBUG: getLoggedUser(): [email protected]
看來工作。
如果我開始一次又一次地刷新頁面,出現這種情況:
DEBUG: JWT Filter
DEBUG: User found: [email protected]
DEBUG: getLoggedUser(): [email protected]
DEBUG: JWT Filter
DEBUG: User found: [email protected]
DEBUG: getLoggedUser(): [email protected]
DEBUG: JWT Filter
DEBUG: User found: [email protected]
DEBUG: getLoggedUser(): null
DEBUG: JWT Filter
DEBUG: User found: [email protected]
DEBUG: getLoggedUser(): [email protected]
第三次,用戶發現在JWTFilter
類,但說到null
控制器內。這很奇怪,因爲過濾器把它放在ContainerRequestContext
裏面,所以這個問題不應該發生。似乎有時ContainerRequestContext
無法保存數據,或在到達控制器時丟失數據。
這裏發生了什麼?爲什麼在撥打ContainerRequestContest#getProperty
時隨機獲得null
對象?我應該這樣做嗎?
值得一提的是我的過濾器是javax.ws.rs.container.ContainerRequestFilter
。我應該改用com.sun.jersey.spi.container.ContainerRequestFilter
嗎?
頭可以包含Java對象得到什麼? – BackSlash
您可以將json對象轉換爲字符串並添加到header.Once數據返回到資源使用jackson映射器轉換回bean類中的json對象/ map。 –
它不是一個json對象,它是一個java對象。對於我來說,每次將對象傳遞爲標題看起來都是不必要的開銷。 'ContainerRequestContext'應該在這裏工作,我不應該使用頭文件。 – BackSlash