@IgnoreUrlsAnnon("/list")
@IgnoreUrlsAnnon("/test")
自定义注解:慎用/list、/test等通用名称,会过滤掉所有/list、/test等方法的token获取。
getApiUserId():取不到值,会被过滤掉。
getUidByToken(httpServletRequest):可以取到值。
getApiUserIdNew():可以取到值。
BaseController.java
/**
* 获得 C端登录人用户id
*
* @return result
*/
protected Integer getApiUserId() {
int intHeader = request.getIntHeader(JwtAdminInfo.apiUserId);
return Math.max(intHeader, 0);
}
/**
* 获得 C端登录人用户id
*
* @return result
*/
protected Long getApiUserIdNew() {
String token = request.getHeader(Header.AUTHORIZATION.getValue());
if (StrUtil.isEmpty(token)) {
return 0L;
}
Claims claimsFromToken = JwtTokenUtil.getClaimsFromToken(token);
String apiUserId = claimsFromToken.get(JwtAdminInfo.apiUserId).toString();
return Long.valueOf(apiUserId);
}
TestController.java
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Header;
import com.alibaba.fastjson.JSON;
import BaseController;
import JwtAdminInfo;
import JwtTokenUtil;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Map;
/**
* @author author
*/
@Api(tags = {"C端--token解析测试"})
@RestController
@RequestMapping("/api/test")
@Slf4j
public class TestController extends BaseController {
@Resource
private RedisTemplate<String, String> redisTemplate;
@PostMapping("/test")
@ApiOperation("测试")
public void test(HttpServletRequest httpServletRequest) {
TestRequest testRequest = new TestRequest();
//token解析用户ID--方法一
Long apiUserId = getApiUserId().longValue();
//token解析用户ID--方法二
Long uid = getApiUserIdNew();
log.info("token获取的uid:[{}], gateway获取的uid:[{}]", uid, apiUserId);
testRequest.setUid(uid);
if (!apiUserId.equals(uid)) {
log.error("token获取的uid:[{}], gateway获取的uid:[{}]", uid, apiUserId);
// 临时添加日志到redis用于gateway错误排查
addRedisLog(testRequest, httpServletRequest);
}
}
//token解析用户ID -- 方法二
private Long getUidByToken(HttpServletRequest httpServletRequest) {
String token = httpServletRequest.getHeader(Header.AUTHORIZATION.getValue());
if (StrUtil.isEmpty(token)) {
return 0L;
}
Claims claimsFromToken = JwtTokenUtil.getClaimsFromToken(token);
String apiUserId = claimsFromToken.get(JwtAdminInfo.apiUserId).toString();
return Long.valueOf(apiUserId);
}
/**
* 临时添加到redis的用于排查gateway问题的日志
*
* @param testRequest
* @param httpServletRequest
*/
private void addRedisLog(TestRequest testRequest, HttpServletRequest httpServletRequest) {
//token解析用户ID -- 方法二
Long newApiUserId = getUidByToken(httpServletRequest);
Map<String, Object> map = new HashMap<>();
Enumeration<String> enumeration = httpServletRequest.getHeaderNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
map.put(key, httpServletRequest.getHeader(key));
}
map.put("uid", "token获取的uid:[" + newApiUserId + "], gateway获取的uid:[" + getApiUserId() + "],");
map.put("TestRequest", testRequest);
redisTemplate.opsForValue().set("TestError::uid-"
.concat(newApiUserId.toString())
.concat("-")
.concat(String.valueOf(System.currentTimeMillis())), JSON.toJSONString(map));
}
}
TestRequest.java
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author author
*/
@Data
public class TestRequest {
@ApiModelProperty(value = "用户ID")
private Long uid;
}
JwtAdminInfo.java
public class JwtAdminInfo {
public static final String apiUserId = "apiUserId";
}
JwtTokenUtil.java
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;
/**
* JwtToken生成的工具类
* JWT token的格式:header.payload.signature
* header的格式(算法、token的类型):
* {"alg": "HS512","typ": "JWT"}
* payload的格式(用户名、创建时间、生成时间):
* {"sub":"wang","created":1489079981393,"exp":1489684781}
* signature的生成算法:
* HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
*/
public class JwtTokenUtil {
public static String prefix = "JwtToken:";
private static String secret = "test_12345678910987654321";
/**
* 根据负责生成JWT的token
*/
public static String generateToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate())
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
/**
* 从token中获取JWT中的负载
*/
public static Claims getClaimsFromToken(String token) {
Claims claims = null;
try {
claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
e.fillInStackTrace();
}
return claims;
}
/**
* 生成token的过期时间
*/
public static Date generateExpirationDate() {
return new Date(33156026044000l);
}
/**
* 从token中获取登录用户名
*/
public static String getUserNameFromToken(String token) {
String username;
try {
Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
/**
* 判断token是否已经失效
*/
private static boolean isTokenExpired(String token) {
Date expiredDate = getExpiredDateFromToken(token);
return expiredDate.before(new Date());
}
/**
* 从token中获取过期时间
*/
private static Date getExpiredDateFromToken(String token) {
Claims claims = getClaimsFromToken(token);
return claims.getExpiration();
}
}