问题描述
我正在关注有关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");
}
}
UserDetailsServiceImpl.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;
}
}
@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"))
文件中,而不是您的代码中。
* 请注意,您设置的值是毫秒 的到期时间。