我已经实现了具有用于登录/注销的REST通道的单面应用程序。我已经开始使用JWT,但我想转向基于会话的通信。我目前是春天的XML配置:由REST服务创建的弹簧安全令牌未保存在会话中
<http pattern="/spring/login" security="none" create-session="always" />
<http pattern="/spring/logout" security="none" create-session="never" />
<http pattern="/spring/**" entry-point-ref="restAuthenticationEntryPoint"
create-session="always">
<csrf disabled="true" />
<custom-filter before="FORM_LOGIN_FILTER" ref="jwtAuthenticationFilter" />
</http>
现在,jwtAuthenticationFilter
被修改,使得它不记录如果验证是否存在,如果不是,它是从头部解析:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// skip if authorization already exists
Authentication sessionAuth = SecurityContextHolder.getContext().getAuthentication();
if (sessionAuth != null) {
LOGGER.info("Already authenticated as {}", sessionAuth.getPrincipal());
chain.doFilter(request, response);
return;
}
LOGGER.info("Try to authorize");
的/春天/ login方法创建令牌,并试图把它变成安全上下文:
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS512), claimsSet);
try {
signedJWT.sign(signer);
String token = "Bearer " + signedJWT.serialize();
response.setToken(token);
Authentication auth = authenticationManager.authenticate(new JWTToken(signedJWT));
SecurityContextHolder.getContext().setAuthentication(auth);
} catch(JOSEException | ParseException e) {
我期待什么,是该令牌将出现在接下来的安全上下文REST呼叫。但是,日志表明,通过下一个请求,令牌不在安全上下文中,它被创建并通过servlet过滤器放到那里,然后它就会出现在后续请求中。
我在这里做错了什么?我期望,如果我要求在/ spring/login调用上创建会话,Authentication
放入SecurityContext
也会在会话中保留。这显然不是这种情况。为了让Spring Security保留REST调用中存储的令牌,我需要做些什么?