gpt4 book ai didi

spring - 如何设计一个好的 JWT 认证过滤器

转载 作者:IT老高 更新时间:2023-10-28 13:45:43 35 4
gpt4 key购买 nike

我是智威汤逊的新手。网络上没有太多可用的信息,因为我是迫不得已才来到这里的。我已经使用 spring session 使用 spring security 开发了一个 spring boot 应用程序。现在我们转向 JWT,而不是 Spring session 。我发现很少有链接,现在我可以验证用户并生成 token 。现在困难的部分是,我想创建一个过滤器,它将对服务器的每个请求进行身份验证,

  1. 过滤器将如何验证 token ? (验证签名就够了?)
  2. 如果其他人窃取了 token 并调用电话,我将如何验证。
  3. 如何绕过过滤器中的登录请求?因为它没有授权 header 。

最佳答案

这是一个过滤器,可以满足您的需求:

public class JWTFilter extends GenericFilterBean {

private static final Logger LOGGER = LoggerFactory.getLogger(JWTFilter.class);

private final TokenProvider tokenProvider;

public JWTFilter(TokenProvider tokenProvider) {

this.tokenProvider = tokenProvider;
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,
ServletException {

try {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String jwt = this.resolveToken(httpServletRequest);
if (StringUtils.hasText(jwt)) {
if (this.tokenProvider.validateToken(jwt)) {
Authentication authentication = this.tokenProvider.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(servletRequest, servletResponse);

this.resetAuthenticationAfterRequest();
} catch (ExpiredJwtException eje) {
LOGGER.info("Security exception for user {} - {}", eje.getClaims().getSubject(), eje.getMessage());
((HttpServletResponse) servletResponse).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
LOGGER.debug("Exception " + eje.getMessage(), eje);
}
}

private void resetAuthenticationAfterRequest() {
SecurityContextHolder.getContext().setAuthentication(null);
}

private String resolveToken(HttpServletRequest request) {

String bearerToken = request.getHeader(SecurityConfiguration.AUTHORIZATION_HEADER);
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
String jwt = bearerToken.substring(7, bearerToken.length());
return jwt;
}
return null;
}
}

并且在过滤器链中包含过滤器:

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

public final static String AUTHORIZATION_HEADER = "Authorization";

@Autowired
private TokenProvider tokenProvider;

@Autowired
private AuthenticationProvider authenticationProvider;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(this.authenticationProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {

JWTFilter customFilter = new JWTFilter(this.tokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);

// @formatter:off
http.authorizeRequests().antMatchers("/css/**").permitAll()
.antMatchers("/images/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/authenticate").permitAll()
.anyRequest().fullyAuthenticated()
.and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
.and().logout().permitAll();
// @formatter:on
http.csrf().disable();

}
}

TokenProvider 类:

public class TokenProvider {

private static final Logger LOGGER = LoggerFactory.getLogger(TokenProvider.class);

private static final String AUTHORITIES_KEY = "auth";

@Value("${spring.security.authentication.jwt.validity}")
private long tokenValidityInMilliSeconds;

@Value("${spring.security.authentication.jwt.secret}")
private String secretKey;

public String createToken(Authentication authentication) {

String authorities = authentication.getAuthorities().stream().map(authority -> authority.getAuthority()).collect(Collectors.joining(","));

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime expirationDateTime = now.plus(this.tokenValidityInMilliSeconds, ChronoUnit.MILLIS);

Date issueDate = Date.from(now.toInstant());
Date expirationDate = Date.from(expirationDateTime.toInstant());

return Jwts.builder().setSubject(authentication.getName()).claim(AUTHORITIES_KEY, authorities)
.signWith(SignatureAlgorithm.HS512, this.secretKey).setIssuedAt(issueDate).setExpiration(expirationDate).compact();
}

public Authentication getAuthentication(String token) {

Claims claims = Jwts.parser().setSigningKey(this.secretKey).parseClaimsJws(token).getBody();

Collection<? extends GrantedAuthority> authorities = Arrays.asList(claims.get(AUTHORITIES_KEY).toString().split(",")).stream()
.map(authority -> new SimpleGrantedAuthority(authority)).collect(Collectors.toList());

User principal = new User(claims.getSubject(), "", authorities);

return new UsernamePasswordAuthenticationToken(principal, "", authorities);
}

public boolean validateToken(String authToken) {

try {
Jwts.parser().setSigningKey(this.secretKey).parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
LOGGER.info("Invalid JWT signature: " + e.getMessage());
LOGGER.debug("Exception " + e.getMessage(), e);
return false;
}
}
}

现在回答你的问题:

  1. 在此过滤器中完成
  2. 保护您的 HTTP 请求,使用 HTTPS
  3. 只允许 /login URI 上的所有内容(我的代码中为 /authenticate)

关于spring - 如何设计一个好的 JWT 认证过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41975045/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com