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
|
@Component
|
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<? extends GrantedAuthority> 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<? extends GrantedAuthority> 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);
|
}
|
|
}
|