Java Spring 401未经授权

问题描述

我正在关注有关Java Spring的教程,并找到了jwt的身份验证代码。到目前为止,没有问题,我可以生成令牌并登录/注册,并将这些令牌用于发布/获取请求的路由。但是问题是,两分钟后,我收到一个401未经授权的错误。而且我解决不了。

我正在关注的教程中的代码

JwtAuthEntryPoint.java

public class JwtAuthEntryPoint implements AuthenticationEntryPoint {
 
    private static final Logger logger = LoggerFactory.getLogger(JwtAuthEntryPoint.class);
    
    @Override
    public void commence(HttpServletRequest request,HttpServletResponse response,AuthenticationException e) 
                             throws IOException,servletexception {
      
        logger.error("Unauthorized error. Message - {}",e.getMessage());
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Error -> Unauthorized");
    }
}

UserDetailsS​​erviceImpl.java

public class JwtAuthTokenFilter extends OncePerRequestFilter {
 
    @Autowired
    private JwtProvider tokenProvider;
 
    @Autowired
    private UserDetailsServiceImpl userDetailsService;
 
    private static final Logger logger = LoggerFactory.getLogger(JwtAuthTokenFilter.class);
 
    @Override
    protected void doFilterInternal(HttpServletRequest request,FilterChain filterChain) 
                        throws servletexception,IOException {
        try {
          
            String jwt = getJwt(request);
            if (jwt!=null && tokenProvider.validateJwtToken(jwt)) {
                String username = tokenProvider.getUserNameFromJwtToken(jwt);
 
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                UsernamePasswordAuthenticationToken authentication 
                    = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
 
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception e) {
            logger.error("Can NOT set user authentication -> Message: {}",e);
        }
 
        filterChain.doFilter(request,response);
    }
 
    private String getJwt(HttpServletRequest request) {
        String authHeader = request.getHeader("Authorization");
          
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
          return authHeader.replace("Bearer ","");
        }
 
        return null;
    }
}

JwtProvider.java

public class JwtProvider {
 
    private static final Logger logger = LoggerFactory.getLogger(JwtProvider.class);
 
    @Value("${grokonez.app.jwtSecret}")
    private String jwtSecret;
 
    @Value("${grokonez.app.jwtExpiration}")
    private int jwtExpiration;
 
    public String generateJwtToken(Authentication authentication) {
 
        UserPrinciple userPrincipal = (UserPrinciple) authentication.getPrincipal();
 
        return Jwts.builder()
                    .setSubject((userPrincipal.getUsername()))
                    .setIssuedAt(new Date())
                    .setExpiration(new Date((new Date()).getTime() + jwtExpiration))
                    .signWith(SignatureAlgorithm.HS512,jwtSecret)
                    .compact();
    }
 
    public String getUserNameFromJwtToken(String token) {
        return Jwts.parser()
                      .setSigningKey(jwtSecret)
                      .parseClaimsJws(token)
                      .getBody().getSubject();
    }
 
    public boolean validateJwtToken(String authToken) {
        try {
            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
            return true;
        } catch (SignatureException e) {
            logger.error("Invalid JWT signature -> Message: {} ",e);
        } catch (MalformedJwtException e) {
            logger.error("Invalid JWT token -> Message: {}",e);
        } catch (ExpiredJwtException e) {
            logger.error("Expired JWT token -> Message: {}",e);
        } catch (UnsupportedJwtException e) {
            logger.error("Unsupported JWT token -> Message: {}",e);
        } catch (IllegalArgumentException e) {
            logger.error("JWT claims string is empty -> Message: {}",e);
        }
        
        return false;
    }
}

WebSecurityConfig.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
    prePostEnabled = true
)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    UserDetailsServiceImpl userDetailsService;
 
    @Autowired
    private JwtAuthEntryPoint unauthorizedHandler;
 
    @Bean
    public JwtAuthTokenFilter authenticationJwtTokenFilter() {
        return new JwtAuthTokenFilter();
    }
 
    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
                .userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }
 
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
 
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().
                authorizeRequests()
                .antMatchers("/api/auth/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        
        http.addFilterBefore(authenticationJwtTokenFilter(),UsernamePasswordAuthenticationFilter.class);
    }
}

非常感谢您的帮助。

解决方法

一切取决于您在//output from mongo client //ran below queries and compared the output from explain. I did not find any difference in //execution stats for performance > db.myCollection.explain("executionStats").update( ... {},... {$pull:{fruits:{$in:["Banana"]}}},... {multi: true} ... ); { "queryPlanner" : { "plannerVersion" : 1,"namespace" : "test.myCollection","indexFilterSet" : false,"parsedQuery" : { },"winningPlan" : { "stage" : "UPDATE","inputStage" : { "stage" : "COLLSCAN","direction" : "forward" } },"rejectedPlans" : [ ] },"executionStats" : { "executionSuccess" : true,"nReturned" : 0,"executionTimeMillis" : 0,"totalKeysExamined" : 0,"totalDocsExamined" : 2,"executionStages" : { "stage" : "UPDATE","executionTimeMillisEstimate" : 0,"works" : 4,"advanced" : 0,"needTime" : 3,"needYield" : 0,"saveState" : 0,"restoreState" : 0,"isEOF" : 1,"nMatched" : 2,"nWouldModify" : 2,"wouldInsert" : false,"nReturned" : 2,"advanced" : 2,"needTime" : 1,"saveState" : 2,"restoreState" : 2,"direction" : "forward","docsExamined" : 2 } } },"serverInfo" : { "host" : "XXXX","port" : XXXX,"version" : "4.2.6","gitVersion" : "XXXX" },"ok" : 1 } > -- > db.myCollection.explain("executionStats").update( ... {},... {$pull: ... {fruits:{$elemMatch:{$in:["Banana"]}}} ... },... {multi: true} ... ); { "queryPlanner" : { "plannerVersion" : 1,"port" : XXX,"ok" : 1 } > 中为setExpiration设置的值。

在您的示例中,您需要更改从配置文件读取的jws.bulder

另一种方式可以替换一些代码,例如:

jwtExpiration

.setExpiration(Date.from(Instant.now() + "your_desired_time")) 文件中,而不是您的代码中。

* 请注意,您设置的值是毫秒 的到期时间。