当jwt令牌无效时,主体对象为null

时间:2020-05-22 02:21:05

标签: java spring spring-boot spring-security

我正在使用Spring Security使用jwt令牌对用户进行身份验证。
当令牌格式错误或过期时,身份验证正常,我得到403 Http状态,如以下配置所示:

 @Bean
public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
    return http
            .exceptionHandling()
            .authenticationEntryPoint((swe, e) -> {
                return Mono.fromRunnable(() -> {
                    swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); 
                });
            }).accessDeniedHandler((swe, e) -> {
                return Mono.fromRunnable(() -> {
                    swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                });
            }).and()
            .csrf().disable()
            .formLogin().disable()
            .httpBasic().disable()
            .authenticationManager(authenticationManager)
            .securityContextRepository(securityContextRepository)
            .authorizeExchange()
            .pathMatchers(HttpMethod.OPTIONS).permitAll()
            .pathMatchers("/**").permitAll()
            .anyExchange().authenticated()
            .and().build();
}

但是,当我使用Spring安全上下文中的Principal或Authentication从jwt令牌中获取用户信息时,如以下代码所示:

@ResponseStatus(HttpStatus.OK)
@GetMapping("/me")
public Mono<ClientDTO> find(final Principal principal) {
    return this.clientService.findByMail(principal.getName());
}

如果令牌格式不正确或已过期,我会从Principal对象得到一个空指针异常,并显示500 https状态。

2 个答案:

答案 0 :(得分:3)

如果我的回答无法解决您的问题,我想立即道歉,因为我看不到您的所有代码。


我有一个合适的项目,我可以在类似的条件下检查Principal对象的工作,并且一切对我都有效。因此,问题不在于此。


您可能在令牌验证方法中引发了异常。像这样的东西:

public boolean validateToken(String token) {
    try {
        Jws<Claims> claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
        return true;
    } catch (JwtException | IllegalArgumentException e) {
        throw new JwtAuthenticationException("JWT token is expired or invalid", e);
    }
}

在这种情况下,在配置中捕获异常之前就已将其捕获。解决方案可能是拒绝令牌验证方法中的新异常,以便将信息输出到日志:

public boolean validateToken(String authToken) {
      try {
         Jwts.parser().setSigningKey(key).parseClaimsJws(authToken);
         return true;
      } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
         log.info("Invalid JWT signature.");
         log.trace("Invalid JWT signature trace: {}", e);
      } catch (ExpiredJwtException e) {
         log.info("Expired JWT token.");
         log.trace("Expired JWT token trace: {}", e);
      } catch (UnsupportedJwtException e) {
         log.info("Unsupported JWT token.");
         log.trace("Unsupported JWT token trace: {}", e);
      } catch (IllegalArgumentException e) {
         log.info("JWT token compact of handler are invalid.");
         log.trace("JWT token compact of handler are invalid trace: {}", e);
      }
      return false;
}

如果能帮到您,我会很高兴。否则,我需要有关您的代码的更多信息。

答案 1 :(得分:0)

@ResponseStatus(HttpStatus.OK)
@GetMapping("/me")
public Mono<ClientDTO> find(final Principal principal) { 

if(principal!=null) return this.clientService.findByMail(principal.getName());
else throw new CustomTokenExpiredException();
}

并删除
.pathMatchers("/**").permitAll()