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 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 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 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 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 cs = (Map) 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 = jwtParser.parseClaimsJws(token); Claims body = claims.getBody(); if (body.getExpiration().before(new Date())) { return false; } Map cs = (Map) 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) { e.printStackTrace(); 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); } } }