oauth-2.0 如何验证Jwt令牌?[已关闭]

qhhrdooz  于 2022-10-31  发布在  其他
关注(0)|答案(2)|浏览(180)

已关闭。此问题需要更多的focused。当前不接受答案。
**想要改进此问题吗?**更新问题,使其仅关注editing this post的一个问题。

三个月前关门了。
Improve this question
我通过两个教程来探索Spring安全性。在其中一个教程中,jwt令牌的验证如下:

public boolean validateToken(String authToken) {
    try {
        Jwts.parser().setSigningKey(appProperties.getAuth().getTokenSecret()).parseClaimsJws(authToken);
        return true;
    } catch (SignatureException ex) {
        logger.error("Invalid JWT signature");
    } catch (MalformedJwtException ex) {
        logger.error("Invalid JWT token");
    } catch (ExpiredJwtException ex) {
        logger.error("Expired JWT token");
    } catch (UnsupportedJwtException ex) {
        logger.error("Unsupported JWT token");
    } catch (IllegalArgumentException ex) {
        logger.error("JWT claims string is empty.");
    }
    return false;
}

而在另一个教程中,则验证如下:

public String extractUsername(String token) {
    return extractClaim(token, Claims::getSubject);
}

public Date extractExpiration(String token) {
    return extractClaim(token, Claims::getExpiration);
}

public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
    final Claims claims = extractAllClaims(token);
    return claimsResolver.apply(claims);
}
private Claims extractAllClaims(String token) {
    return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}

private Boolean isTokenExpired(String token) {
    return extractExpiration(token).before(new Date());
}

public Boolean validateToken(String token, UserDetails userDetails) {
    final String username = extractUsername(token);
    return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}

我有几个疑问:

**Q1.**第二个例子没有捕获异常。捕获和记录异常是否应该是验证的一部分?或者第二个例子确实做了一些我无法发现的类似的事情?
**问题2.**令牌过期是通过捕获ExpiredJwtException来处理的,而第二个示例使用isTokenExpired()显式检查令牌过期。理想情况下应该如何完成?
**问题3.**第二个示例显式检查令牌中的username是否确实与当前安全上下文中的用户名username.equals(userDetails.getUsername())相同。我不知道它会如何,因为我相信安全上下文本身将使用当前令牌来填充。2因此我觉得这个条件将总是平凡地为真。3我说得对吗?这是否也是第一个示例没有对此进行显式检查的原因?

e0bqpujr

e0bqpujr1#

这两种方法都有缺陷,因为它们都实现了自定义安全性,这通常是不好的做法。
如果您使用的是spring security,则不需要编写像令牌这样重要的自定义验证,因为spring security已经拥有完整的JWTSupport好几年了。
文档中有一整章是关于如何配置Spring Security附带的内置JWTFilter的,只需添加一行就可以了。
https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html#oauth2resourceserver-jwt-architecture
jwt过滤器的标准启用:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(authorize -> authorize
            .anyRequest().authenticated()
        )
        .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
    return http.build();
}

配置验证jwt的方式:

@Bean
JwtDecoder jwtDecoder() {
    return NimbusJwtDecoder.withSecretKey(this.key)
            .jwsAlgorithm(RS512).build();
}

还有其他几项需要配置。

ssgvzors

ssgvzors2#

第二个例子没有捕获异常。捕获和记录异常是否应该是验证的一部分?或者第二个例子确实在做一些我无法发现的类似的事情?
根据我的意见,我们应该捕获异常,并将其 Package 在带有错误代码的业务异常中,因为这样更容易进行故障排除。

相关问题