package com.sandu.common.security.jwt; import com.sandu.common.security.config.SecurityProperties; import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.security.Key; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.stream.Collectors; /** * @author chenjiantian * @date 2021/4/23 16:43 */ @Slf4j public class JwtTokenProvider implements InitializingBean { private static final String AUTHORITIES_KEY = "auth"; private static final String CREDENTIALS_KEY = "cred"; private final SecurityProperties properties; private Key key; public JwtTokenProvider(SecurityProperties properties) { this.properties = properties; } @Override public void afterPropertiesSet() throws Exception { byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret()); this.key = Keys.hmacShaKeyFor(keyBytes); } /** * 根据认证信息生成一个token */ public String createToken(Authentication authentication) { String authorities = authentication.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.joining(",")); long now = (new Date()).getTime(); Date expiration = new Date(now + properties.getTokenValidityInSeconds()); return Jwts.builder() .setSubject(authentication.getName()) .claim(AUTHORITIES_KEY, authorities) .claim(CREDENTIALS_KEY, authentication.getCredentials()) .setExpiration(expiration) .signWith(key, SignatureAlgorithm.HS512) .compact(); } /** * 根据token获取认证信息 */ public Authentication getAuthentication(String token) { Claims claims = Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody(); Collection authorities = Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); User principal = new User(claims.getSubject(), "", authorities); return new UsernamePasswordAuthenticationToken(principal, claims.get(CREDENTIALS_KEY), authorities); } /** * 验证token有效性 */ public boolean validateToken(String authToken) { try { Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(authToken); return true; } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { log.info("Invalid JWT signature."); e.printStackTrace(); } catch (ExpiredJwtException e) { log.info("Expired JWT token."); e.printStackTrace(); } catch (UnsupportedJwtException e) { log.info("Unsupported JWT token."); e.printStackTrace(); } catch (IllegalArgumentException e) { log.info("JWT token compact of handler are invalid."); e.printStackTrace(); } return false; } /** * 获取请求头的token */ public String getToken(HttpServletRequest request) { final String requestHeader = request.getHeader(properties.getHeader()); if (requestHeader != null && requestHeader.startsWith(properties.getTokenStartWith())) { return requestHeader.substring(properties.getTokenStartWith().length()); } return null; } public Throwable getException(String authToken) { try { Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(authToken); return null; } catch (Exception e) { return e; } } /** * 获取Claims 不论是不是jwt过期 * @param token * @return */ public Claims getClaimsForce(String token) { try { Claims claims = Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody(); return claims; } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { log.info("Invalid JWT signature."); } catch (ExpiredJwtException e) { log.info("Expired JWT token."); return e.getClaims(); } catch (UnsupportedJwtException e) { log.info("Unsupported JWT token."); } catch (IllegalArgumentException e) { log.info("JWT token compact of handler are invalid."); } return null; } /** * 获取subject 不论是不是jwt过期 * @param token * @return */ public String getSubjectForce(String token) { Claims claimsForce = getClaimsForce(token); if(claimsForce != null){ return claimsForce.getSubject(); } return null; } /** * 刷新token 把过期的token 刷新 * @param oldToken * @return */ public String refreshToken(String oldToken) { Claims claimsForce = getClaimsForce(oldToken); if(claimsForce == null){ return null; } Collection authorities = Arrays.stream(claimsForce.get(AUTHORITIES_KEY).toString().split(",")) .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); User principal = new User(claimsForce.getSubject(), "", authorities); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(principal, "", authorities); return createToken(authenticationToken); } }