Springsecurity:why check 如果在授权筛选器中设置了身份验证令牌?

bfrts1fy  于 2021-07-13  发布在  Java
关注(0)|答案(1)|浏览(292)

我在试着理解 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,对吗?如果用户没有通过身份验证,为什么要继续请求?如果要进行身份验证筛选,那么为什么在身份验证筛选之前调用授权筛选?

1yjd4xko

1yjd4xko1#

在springsecurity中,过滤器链基本上是一个链表。所以当你做一个请求时,它会命中第一个过滤器,这个过滤器会调用链接中的下一个链,然后下一个,下一个,等等。

// Get a specific header (im guessing authorization header)
String header = req.getHeader(HEADER_STRING);

// If no such header was found, or the found header does not include a specific prefix 
// (im guessing the string Baerer) which means that if this is not a
// authentication header containing a baerer token, then call the next filter in 
// the chain.. The next filter will have the same call, etc.
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
    chain.doFilter(req, res);
    return;
}

如果一个请求在没有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解决方案,它只需要定制。所以这个自定义过滤器是多余的。

相关问题