|
@@ -0,0 +1,217 @@
|
|
|
+package com.lantone.common.service.impl;
|
|
|
+
|
|
|
+import com.auth0.jwt.JWT;
|
|
|
+import com.auth0.jwt.exceptions.JWTDecodeException;
|
|
|
+import com.auth0.jwt.interfaces.Claim;
|
|
|
+import com.auth0.jwt.interfaces.DecodedJWT;
|
|
|
+import com.lantone.common.dto.JwtStore;
|
|
|
+import com.lantone.common.exception.Asserts;
|
|
|
+import com.lantone.common.service.SysTokenService;
|
|
|
+import com.lantone.common.util.DateUtil;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
+import org.springframework.dao.DataAccessException;
|
|
|
+import org.springframework.data.redis.connection.RedisConnection;
|
|
|
+import org.springframework.data.redis.core.RedisCallback;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @Description: Token验证类 实现
|
|
|
+ * @author: gaodm
|
|
|
+ * @time: 2018/10/29 13:34
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class SysTokenServiceImpl implements SysTokenService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ @Qualifier("redisTemplateForToken")
|
|
|
+ RedisTemplate redisForToken;
|
|
|
+
|
|
|
+ private byte[] serializeKey(Object o) {
|
|
|
+ return redisForToken.getKeySerializer().serialize(o);
|
|
|
+ }
|
|
|
+
|
|
|
+ private byte[] serializeValue(Object o) {
|
|
|
+ return redisForToken.getValueSerializer().serialize(o);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Object deserializeValue(byte[] b) {
|
|
|
+ return redisForToken.getValueSerializer().deserialize(b);
|
|
|
+ }
|
|
|
+
|
|
|
+ private byte[] getUserTokenKey(String userId) {
|
|
|
+ String userTokensFormat = "user_tokens_%s";
|
|
|
+ return serializeKey(String.format(userTokensFormat, userId));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建token
|
|
|
+ *
|
|
|
+ * @param token 用户token
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Boolean createToken(JwtStore token) {
|
|
|
+ DecodedJWT jwt = decodedJWT(token.getRefreshToken());
|
|
|
+ Map<String, Claim> claims = jwt.getClaims();
|
|
|
+ String userId = claims.get("id").asInt().toString();
|
|
|
+ Date expDate = claims.get("exp").asDate();
|
|
|
+ final byte[] redis_key = getUserTokenKey(userId);
|
|
|
+ redisForToken.execute(new RedisCallback<Object>() {
|
|
|
+ @Override
|
|
|
+ public Object doInRedis(RedisConnection connection) throws DataAccessException {
|
|
|
+ //获取旧的
|
|
|
+ byte[] bytes = connection.get(redis_key);
|
|
|
+ //删除旧的
|
|
|
+ if (bytes != null) {
|
|
|
+ connection.del(bytes);
|
|
|
+ }
|
|
|
+ //设置新的
|
|
|
+ connection.setEx(
|
|
|
+ redis_key,
|
|
|
+ (expDate.getTime() - DateUtil.now().getTime()) / 1000,
|
|
|
+ serializeValue(token)
|
|
|
+ );
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ private DecodedJWT decodedJWT(String token) {
|
|
|
+ try {
|
|
|
+ DecodedJWT jwt = JWT.decode(token);
|
|
|
+ return jwt;
|
|
|
+ } catch (JWTDecodeException var2) {
|
|
|
+ var2.printStackTrace();
|
|
|
+ Asserts.fail("token解析失败!");
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证token是否有效
|
|
|
+ *
|
|
|
+ * @param token 待验证的token
|
|
|
+ * @param type 1:accessToken,2:refreshToken
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Boolean verifyToken(String token, Integer type) {
|
|
|
+ Boolean res = false;
|
|
|
+ if (null == token) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ DecodedJWT jwt = decodedJWT(token);
|
|
|
+ Map<String, Claim> claims = jwt.getClaims();
|
|
|
+ Claim claim = (Claim)claims.get("id");
|
|
|
+ String userId = claim.asInt().toString();
|
|
|
+ //从redis中取出
|
|
|
+ final byte[] redis_key = getUserTokenKey(userId);
|
|
|
+ JwtStore tokenStore = (JwtStore) redisForToken.execute(new RedisCallback<JwtStore>() {
|
|
|
+ @Override
|
|
|
+ public JwtStore doInRedis(RedisConnection connection) throws DataAccessException {
|
|
|
+ byte[] bytes = connection.get(redis_key);
|
|
|
+ if (bytes == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return (JwtStore) deserializeValue(bytes);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (null != tokenStore) {
|
|
|
+ if (type == 1) {
|
|
|
+ if (null != tokenStore.getAccessToken() && tokenStore.getAccessToken().equals(token)) {
|
|
|
+ res = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type == 2) {
|
|
|
+ if (null != tokenStore.getRefreshToken() && tokenStore.getRefreshToken().equals(token)) {
|
|
|
+ res = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除用户token
|
|
|
+ *
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @return 删除是否成功
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Boolean deleteToken(String userId) {
|
|
|
+ final byte[] redis_key = getUserTokenKey(userId);
|
|
|
+ Long l = (Long) redisForToken.execute(new RedisCallback<Long>() {
|
|
|
+ @Override
|
|
|
+ public Long doInRedis(RedisConnection connection) throws DataAccessException {
|
|
|
+ return connection.del(redis_key);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return l > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量删除用户token
|
|
|
+ *
|
|
|
+ * @param userIds 用户列表
|
|
|
+ * @return 删除是否成功
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Boolean deleteBatchToken(List<Long> userIds) {
|
|
|
+ Long l = (Long) redisForToken.execute(new RedisCallback<Long>() {
|
|
|
+ @Override
|
|
|
+ public Long doInRedis(RedisConnection connection) throws DataAccessException {
|
|
|
+ connection.openPipeline();
|
|
|
+ Long cnt = 0L;
|
|
|
+ for (Long userId : userIds) {
|
|
|
+ byte[] redis_key = getUserTokenKey(userId.toString());
|
|
|
+ connection.del(redis_key);
|
|
|
+ cnt++;
|
|
|
+ }
|
|
|
+ connection.closePipeline();
|
|
|
+ return cnt;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return l > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户jwt
|
|
|
+ *
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @return jwt信息
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public JwtStore getToken(String userId) {
|
|
|
+ JwtStore tokenStore = null;
|
|
|
+ //从redis中取出
|
|
|
+ final byte[] redis_key = getUserTokenKey(userId);
|
|
|
+ tokenStore = (JwtStore) redisForToken.execute(new RedisCallback<JwtStore>() {
|
|
|
+ @Override
|
|
|
+ public JwtStore doInRedis(RedisConnection connection) throws DataAccessException {
|
|
|
+ byte[] bytes = connection.get(redis_key);
|
|
|
+ if (bytes == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return (JwtStore) deserializeValue(bytes);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return tokenStore;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getUserIDByToken(String token) {
|
|
|
+ DecodedJWT jwt = decodedJWT(token);
|
|
|
+ Map<String, Claim> claims = jwt.getClaims();
|
|
|
+ return claims.get("id").asInt().toString();
|
|
|
+ }
|
|
|
+}
|