141 lines
5.2 KiB
Java
141 lines
5.2 KiB
Java
package com.zhgd.xmgl.security;
|
||
|
||
import cn.hutool.core.util.IdUtil;
|
||
import com.zhgd.exception.CustomException;
|
||
import com.zhgd.redis.lock.RedisRepository;
|
||
import com.zhgd.xmgl.modules.basicdata.mapper.SystemUserMapper;
|
||
import com.zhgd.xmgl.util.EnvironmentUtil;
|
||
import io.jsonwebtoken.*;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.beans.factory.annotation.Value;
|
||
import org.springframework.http.HttpStatus;
|
||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||
import org.springframework.security.core.Authentication;
|
||
import org.springframework.security.core.userdetails.UserDetails;
|
||
import org.springframework.stereotype.Component;
|
||
|
||
import javax.annotation.PostConstruct;
|
||
import javax.servlet.http.HttpServletRequest;
|
||
import java.util.*;
|
||
import java.util.concurrent.ConcurrentHashMap;
|
||
|
||
/**
|
||
* @program: devManage
|
||
* @description: JWTtoken生成工具
|
||
* @author: Mr.Peng
|
||
* @create: 2019-09-24 10:46
|
||
**/
|
||
@Component
|
||
@Slf4j
|
||
public class JwtTokenProvider {
|
||
@Value("${security.jwt.token.secret-key}")
|
||
private String secretKey;
|
||
@Value("${userTokenExpireMinute:10}")
|
||
private Integer userTokenExpireMinute;
|
||
@Autowired
|
||
private RedisRepository redisRepository;
|
||
private final String USER_TOKEN_EXPIRE_PREFIX = "USER_TOKEN_EXPIRE:";
|
||
private static ConcurrentHashMap<String, String> userMap = new ConcurrentHashMap<>();
|
||
|
||
@Autowired
|
||
private MyUserDetailsImpl myUserDetailsImpl;
|
||
|
||
@PostConstruct
|
||
protected void init() {
|
||
secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
|
||
}
|
||
|
||
/**
|
||
* @param username
|
||
* @param validityInMilliseconds 单位是秒
|
||
* @return
|
||
*/
|
||
public String createToken(String username, Integer validityInMilliseconds) {
|
||
return createToken(username, validityInMilliseconds, null);
|
||
}
|
||
|
||
/**
|
||
* @param username
|
||
* @param validityInMilliseconds 单位是秒
|
||
* @return
|
||
*/
|
||
public String createToken(String username, Integer validityInMilliseconds, Integer loginTimeOut) {
|
||
String uuid = IdUtil.simpleUUID();
|
||
Map<String, Object> claims = new HashMap<>();
|
||
claims.put("uuid", uuid);
|
||
claims.put("account", username);
|
||
claims.put("loginTimeOut", loginTimeOut);
|
||
Date now = new Date();
|
||
Date validity = new Date(now.getTime() + validityInMilliseconds * 1000L);
|
||
String token = Jwts.builder()//
|
||
.setClaims(claims)//
|
||
.setIssuedAt(now)//
|
||
.setExpiration(validity)//过期时间秒
|
||
.signWith(SignatureAlgorithm.HS256, secretKey)//
|
||
.compact();
|
||
userMap.put(username, token);
|
||
//刷新token
|
||
String key = USER_TOKEN_EXPIRE_PREFIX + EnvironmentUtil.getActiveEnvironment() + ":" + username + ":" + uuid;
|
||
redisRepository.set(key, "", userTokenExpireMinute * 60L);
|
||
return token;
|
||
}
|
||
|
||
public Authentication getAuthentication(String token) {
|
||
UserDetails userDetails = myUserDetailsImpl.loadUserByUsername(getUsername(token));
|
||
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
|
||
}
|
||
|
||
public String getUsername(String token) {
|
||
Map<String, Object> cs = (Map<String, Object>) Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
|
||
return (String) cs.get("account");
|
||
}
|
||
|
||
public String resolveToken(HttpServletRequest req) {
|
||
//String bearerToken=req.getParameter("token");
|
||
String bearerToken = req.getHeader("Authorization");
|
||
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
|
||
return bearerToken.substring(7);
|
||
}
|
||
return bearerToken;
|
||
}
|
||
|
||
public boolean validateToken(String token) {
|
||
try {
|
||
JwtParser jwtParser = Jwts.parser().setSigningKey(secretKey);
|
||
Jws<Claims> claims = jwtParser.parseClaimsJws(token);
|
||
Claims body = claims.getBody();
|
||
if (body.getExpiration().before(new Date())) {
|
||
return false;
|
||
}
|
||
|
||
Map<String, Object> cs = (Map<String, Object>) body;
|
||
if (Objects.equals(cs.get("loginTimeOut"), 1)) {
|
||
//判断token过期没有
|
||
String key = USER_TOKEN_EXPIRE_PREFIX + EnvironmentUtil.getActiveEnvironment() + ":" + cs.get("account") + ":" + cs.get("uuid");
|
||
if (redisRepository.get(key) == null) {
|
||
return false;
|
||
}
|
||
//刷新token
|
||
redisRepository.set(key, "", userTokenExpireMinute * 60L);
|
||
}
|
||
return true;
|
||
} catch (JwtException | IllegalArgumentException e) {
|
||
log.error("error:", e);
|
||
throw new CustomException("Expired or invalid JWT token", HttpStatus.FORBIDDEN);
|
||
}
|
||
}
|
||
|
||
public void valiadteLogin(String token) {
|
||
String userName = getUsername(token);
|
||
if (userMap.containsKey(userName)) {
|
||
if (!token.equals(userMap.get(userName))) {
|
||
throw new CustomException("该账户已其他地方登录", HttpStatus.FORBIDDEN);
|
||
}
|
||
} else {
|
||
userMap.put(userName, token);
|
||
}
|
||
}
|
||
|
||
}
|