我一直致力于基于Spring的服务,使用JWT进行身份验证。
处理用户请求的服务在过滤器中调用授权服务,该过滤器设置安全上下文,看起来非常像这样:
@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private AuthorizationServiceClient authorizationServiceClient;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
User user = authorizationServiceClient.requestUserFromToken(request.getHeader("X-Auth-Token"));
SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(user));
filterChain.doFilter(request, response);
SecurityContextHolder.getContext().setAuthentication(null);
} catch (HttpClientErrorException e) {
response.sendError(e.getStatusCode().value());
}
}
}
AuthorizationServiceClient调用远程服务,该服务处理用户角色和凭据的验证。
我一直面临着一种非常奇怪的行为:
当我的UI上的某个页面同时发出多个请求时,我最终得到一个500,由NullPointerException引起。
根本原因是Principal(包含用户的身份)为null,当它不应该有。
答案 0 :(得分:1)
经过一次痛苦的调查后,我结束了,确认SecurityContextHolder,即使它使用的是ThreadLocal,也在使用会话,然后在线程之间共享。
当SecurityContextHolder.getContext().setAuthentication(null);
在同一会话中发出某些请求并且正在导致NPE时,http.
[...]
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).
[...]
正在删除并发线程中使用的值。
所以,如果像我一样,你想阻止使用会话,你需要使用以下方式设置安全性:
CREATE OR REPLACE TRIGGER TRG_LINE_PRODUCT AFTER INSERT UPDATE OR DELETE ON
TBL_CH08_LINE FOR EACH ROW
BEGIN
IF INSERTING THEN UPDATE TBL_CH08_PRODUCT P SET P_QOH = P_QOH-:NEW.LINE.UNITS
WHERE P.P_CODE = :NEW.P.P_CODE;
END IF;
END;
/