wujian
2024-03-22 0ce25f34a0d627a5cc0d073d24b8c3e569feac15
提交 | 用户 | 时间
e57a89 1 package com.jcdm.framework.web.service;
2
3 import java.util.HashMap;
4 import java.util.Map;
5 import java.util.concurrent.TimeUnit;
6 import javax.servlet.http.HttpServletRequest;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.beans.factory.annotation.Value;
11 import org.springframework.stereotype.Component;
12 import com.jcdm.common.constant.CacheConstants;
13 import com.jcdm.common.constant.Constants;
14 import com.jcdm.common.core.domain.model.LoginUser;
15 import com.jcdm.common.core.redis.RedisCache;
16 import com.jcdm.common.utils.ServletUtils;
17 import com.jcdm.common.utils.StringUtils;
18 import com.jcdm.common.utils.ip.AddressUtils;
19 import com.jcdm.common.utils.ip.IpUtils;
20 import com.jcdm.common.utils.uuid.IdUtils;
21 import eu.bitwalker.useragentutils.UserAgent;
22 import io.jsonwebtoken.Claims;
23 import io.jsonwebtoken.Jwts;
24 import io.jsonwebtoken.SignatureAlgorithm;
25
26 /**
27  * token验证处理
28  *
29  * @author jc
30  */
31 @Component
32 public class TokenService
33 {
34     private static final Logger log = LoggerFactory.getLogger(TokenService.class);
35
36     // 令牌自定义标识
37     @Value("${token.header}")
38     private String header;
39
40     // 令牌秘钥
41     @Value("${token.secret}")
42     private String secret;
43
44     // 令牌有效期(默认30分钟)
45     @Value("${token.expireTime}")
46     private int expireTime;
47
48     protected static final long MILLIS_SECOND = 1000;
49
50     protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
51
52     private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
53
54     @Autowired
55     private RedisCache redisCache;
56
57     /**
58      * 获取用户身份信息
59      *
60      * @return 用户信息
61      */
62     public LoginUser getLoginUser(HttpServletRequest request)
63     {
64         // 获取请求携带的令牌
65         String token = getToken(request);
66         if (StringUtils.isNotEmpty(token))
67         {
68             try
69             {
70                 Claims claims = parseToken(token);
71                 // 解析对应的权限以及用户信息
72                 String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
73                 String userKey = getTokenKey(uuid);
74                 LoginUser user = redisCache.getCacheObject(userKey);
75                 return user;
76             }
77             catch (Exception e)
78             {
79                 log.error("获取用户信息异常'{}'", e.getMessage());
80             }
81         }
82         return null;
83     }
84
85     /**
86      * 设置用户身份信息
87      */
88     public void setLoginUser(LoginUser loginUser)
89     {
90         if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
91         {
92             refreshToken(loginUser);
93         }
94     }
95
96     /**
97      * 删除用户身份信息
98      */
99     public void delLoginUser(String token)
100     {
101         if (StringUtils.isNotEmpty(token))
102         {
103             String userKey = getTokenKey(token);
104             redisCache.deleteObject(userKey);
105         }
106     }
107
108     /**
109      * 创建令牌
110      *
111      * @param loginUser 用户信息
112      * @return 令牌
113      */
114     public String createToken(LoginUser loginUser)
115     {
116         String token = IdUtils.fastUUID();
117         loginUser.setToken(token);
118         setUserAgent(loginUser);
119         refreshToken(loginUser);
120
121         Map<String, Object> claims = new HashMap<>();
122         claims.put(Constants.LOGIN_USER_KEY, token);
123         return createToken(claims);
124     }
125
126     /**
127      * 验证令牌有效期,相差不足20分钟,自动刷新缓存
128      *
129      * @param loginUser
130      * @return 令牌
131      */
132     public void verifyToken(LoginUser loginUser)
133     {
134         long expireTime = loginUser.getExpireTime();
135         long currentTime = System.currentTimeMillis();
136         if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
137         {
138             refreshToken(loginUser);
139         }
140     }
141
142     /**
143      * 刷新令牌有效期
144      *
145      * @param loginUser 登录信息
146      */
147     public void refreshToken(LoginUser loginUser)
148     {
149         loginUser.setLoginTime(System.currentTimeMillis());
150         loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
151         // 根据uuid将loginUser缓存
152         String userKey = getTokenKey(loginUser.getToken());
153         redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
154     }
155
156     /**
157      * 设置用户代理信息
158      *
159      * @param loginUser 登录信息
160      */
161     public void setUserAgent(LoginUser loginUser)
162     {
163         UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
164         String ip = IpUtils.getIpAddr();
165         loginUser.setIpaddr(ip);
166         loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
167         loginUser.setBrowser(userAgent.getBrowser().getName());
168         loginUser.setOs(userAgent.getOperatingSystem().getName());
169     }
170
171     /**
172      * 从数据声明生成令牌
173      *
174      * @param claims 数据声明
175      * @return 令牌
176      */
177     private String createToken(Map<String, Object> claims)
178     {
179         String token = Jwts.builder()
180                 .setClaims(claims)
181                 .signWith(SignatureAlgorithm.HS512, secret).compact();
182         return token;
183     }
184
185     /**
186      * 从令牌中获取数据声明
187      *
188      * @param token 令牌
189      * @return 数据声明
190      */
191     private Claims parseToken(String token)
192     {
193         return Jwts.parser()
194                 .setSigningKey(secret)
195                 .parseClaimsJws(token)
196                 .getBody();
197     }
198
199     /**
200      * 从令牌中获取用户名
201      *
202      * @param token 令牌
203      * @return 用户名
204      */
205     public String getUsernameFromToken(String token)
206     {
207         Claims claims = parseToken(token);
208         return claims.getSubject();
209     }
210
211     /**
212      * 获取请求token
213      *
214      * @param request
215      * @return token
216      */
217     private String getToken(HttpServletRequest request)
218     {
219         String token = request.getHeader(header);
220         if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
221         {
222             token = token.replace(Constants.TOKEN_PREFIX, "");
223         }
224         return token;
225     }
226
227     private String getTokenKey(String uuid)
228     {
229         return CacheConstants.LOGIN_TOKEN_KEY + uuid;
230     }
231 }