我在试着理解 Spring 安全。我遇到了下面的代码
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
public JWTAuthorizationFilter(AuthenticationManager authManager) {
super(authManager);
}
@Override
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain) throws IOException, ServletException {
String header = req.getHeader(HEADER_STRING);
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
chain.doFilter(req, res);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(req, res);
}
// Reads the JWT from the Authorization header, and then uses JWT to validate the token
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
if (token != null) {
// parse the token.
String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes()))
.build()
.verify(token.replace(TOKEN_PREFIX, ""))
.getSubject();
if (user != null) {
// new arraylist means authorities
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
你需要什么
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
chain.doFilter(req, res);
return;
}
授权后会做认证吗?在这种情况下,将设置标题。我遗漏了什么?还有什么是 chain.doFilter()
你到底在做什么?它用于继续并最终命中servlet,对吗?如果用户没有通过身份验证,为什么要继续请求?如果要进行身份验证筛选,那么为什么在身份验证筛选之前调用授权筛选?
1条答案
按热度按时间1yjd4xko1#
在springsecurity中,过滤器链基本上是一个链表。所以当你做一个请求时,它会命中第一个过滤器,这个过滤器会调用链接中的下一个链,然后下一个,下一个,等等。
如果一个请求在没有auth头的情况下被发送,并且我们进入应用程序,当我们到达实际的端点时,沿着过滤链向下,它可能会有一个anotation说您需要一个特定的角色,而用户不会有这个角色,因为它本身没有经过身份验证。结果将从安全框架返回401个未经授权的文件。
另一方面,如果它发现一个带有
bearer
prefix它将尝试从报头中提取令牌,验证其完整性,确保没有人篡改它,对其进行解码,并获取subject
令牌中的字段。使用主题将创建一个UsernamePasswordAuthenticationToken
并将其设置为安全上下文中经过身份验证的令牌。基本上设置subject
作为经过身份验证的用户。如果令牌中没有主题,filter将返回null(这是草率的编码,可能会使应用程序崩溃,应该抛出401异常)。
此代码有几个缺点:
String header = req.getHeader(HEADER_STRING);
叫了两次默认的用户案例是尝试登录的用户,应该是相反的方式,默认的案例应该是抛出一个401未经授权和所有的逻辑应该尽量防止。
如果
authorization
包含字符串的标头bearer
但是不发送令牌解析函数将返回空值,并且过滤器将调用setAuthentication
有价值的null
可能会导致车祸。如果
authorization
包含字符串的标头bearer
令牌不包含subject
解析函数将返回一个空值,并且过滤器将调用setAuthentication
有价值的null
可能会导致车祸。spring已经包含了对
Nimbus
jwt库编码和解码jwt的,没有必要拉在另一个库java-jwt
如上述示例所示。值得一提的是,从spring5开始,springsecurity中已经有一个完全实现的jwt解决方案,它只需要定制。所以这个自定义过滤器是多余的。