GlobalFilter过滤器进行token验证
- JwtFactory和redis的MAVEN依赖
- JwtFactory生成token(身份令牌):代码部分
- 工具类代码:
- token认证认证部分代码:
GlobalFilter过滤器代码部分
import com.alibaba.fastjson.JSONObject;
import demo.utils.JwtConstant;
import demo.utils.JwtFactory;
import demo.utils.TokenCacheUtil;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
@Configuration
public class IsLoginGateway implements GlobalFilter,Ordered {
@Autowired
private TokenCacheUtil tokenCacheUtil;
@Override
public int getOrder() {
return 1;
}
//拉取token过期时间
@Value("${token.expire:43200000}")
@RefreshScope
public void setExpire(Long expire) {
if (expire != null) {
JwtConstant.JWT_REFRESH_TTL = Long.valueOf(expire);
}
}
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String userId = getLoginUserId(exchange);
if (request.getMethod().name().equalsIgnoreCase("OPTIONS")) {
JSONObject message = new JSONObject();
message.put("statusCode", -1);
message.put("msg", "请求类型错误!!!");
byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bits);
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//指定编码,否则在浏览器中会中文乱码
response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
}
if (StringUtils.isNotBlank(userId)) {
exchange.getResponse().getHeaders().set("isLogin", userId);
} else {
exchange.getResponse().getHeaders().set("isLogin", "-1");
JSONObject message = new JSONObject();
message.put("statusCode", -1);
message.put("msg", "鉴权失败");
byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bits);
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//指定编码,否则在浏览器中会中文乱码
response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
}
return chain.filter(exchange);
}
private String getLoginUserId(ServerWebExchange exchange) {
String userId = null;
String auth =exchange.getRequest().getHeaders().getFirst("Authorization");
if ((auth != null) && (auth.length() > 7)) {
Claims claims = JwtFactory.parseJWT(auth);
if (claims != null) {
userId = claims.get("userid") == null ? "" : claims.get("userid").toString();
if (!tokenCacheUtil.checkTokenExists(auth, Integer.valueOf(userId))) {
return null;
}
exchange.getAttributes().put("userid",userId);
}
}
return userId;
}
}
JwtFactory和redis的MAVEN依赖
io.jsonwebtoken
jjwt
0.7.0
org.springframework.boot
spring-boot-starter-data-redis
1.5.13.RELEASE
JwtFactory生成token(身份令牌):代码部分
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
/**
* Description:
* Created with edanelx.
* Create in: 2018/3/29 07:20
*/
public class JwtFactory {
public JwtFactory() {
}
private static SecretKey generalKey() {
String stringKey = "Mpk4ZjZim2Q0Nj0xZDMpM2NhZlU0ZTgzMrYyN2IpZjY";
byte[] encodedKey = Base64.encode(stringKey.getBytes()).getBytes();
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
public static Claims parseJWT(String jsonWebToken) {
try {
SecretKey key = generalKey();
Claims claims = (Claims) Jwts.parser().setSigningKey(key).parseClaimsJws(jsonWebToken).getBody();
return claims;
} catch (Exception var3) {
return null;
}
}
public static String createJWT(String name, String userId) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
SecretKey signingKey = generalKey();
JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT").claim("unique_name", name).claim("userid", userId).setIssuer("pc.api.yobtc.com").setAudience("098f6bcd4621d373cade4e832627b4f6").setIssuedAt(now).signWith(signatureAlgorithm, signingKey);
if (JwtConstant.JWT_REFRESH_TTL >= 0L) {
long expMillis = nowMillis + JwtConstant.JWT_REFRESH_TTL;
Date exp = new Date(expMillis);
builder.setExpiration(exp).setNotBefore(now);
}
return builder.compact();
}
}
工具类代码:
public class JwtConstant
{
public static final String JWT_ID = "098f6bcd4621d373cade4e832627b4f6";
public static final String JWT_NAME = "pc.api.yobtc.com";
public static final String JWT_SECRET = "Mpk4ZjZim2Q0Nj0xZDMpM2NhZlU0ZTgzMrYyN2IpZjY";
public static final int JWT_TTL = 3600000;
public static final int JWT_REFRESH_INTERVAL = 3300000;
/* 15 */ public static long JWT_REFRESH_TTL = 3600000L;
}
public class Constants {
/*
* token Key
*/
public static final String TOKEN_KEY_PERFIX = "AUTH_TOKEN_";
/**
* 拦截器返回值:token错误
*/
public static final int ERROR_RESPONSE_TOKEN_CODE = 1000;
public static final String ERROR_RESPONSE_AUTH_TOKEN_TIMEOUT = "token过期,请重新登录";
public static final String ERROR_RESPONSE_AUTH_PARSE = "无效的token";
}
token认证认证部分代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import java.util.concurrent.TimeUnit;
@Repository
public class TokenCacheUtil {
@Autowired
private StringRedisTemplate redisTemplate;
/*@Value("${debug}")
private boolean debug;*/
private static final String CACHE_KEY_PREFIX = "user:token:pc:";
private static final Integer[] BOSS_UID = new Integer[]{
271498,
427928,
41458,
246527,
427190,
393068,
309,
427837,
427076,
425074,
710274,
1066,
832086,
832082,
832079,
832081,
832084,
832078,
832083,
832080,
832087,
832092,
832091,
832094,
832085,
832265,
832089,
708432,
708910,
1000735,
800361,
1381946,
1383092
};
private String getCacheKeyByUserId(Integer userId) {
return CACHE_KEY_PREFIX + userId.toString();
}
public void saveToken(String token, Integer userId) {
redisTemplate.opsForValue().set(getCacheKeyByUserId(userId), token);
// redisTemplate.exp
redisTemplate.expire(getCacheKeyByUserId(userId), new Long(JwtConstant.JWT_REFRESH_TTL / 1000),TimeUnit.SECONDS);
}
public boolean checkTokenExists(String token, Integer userId) {
for (Integer uid : BOSS_UID) {
if (uid.equals(userId)) {
return true;
}
}
String redisToken = redisTemplate.opsForValue().get(getCacheKeyByUserId(userId));
return redisToken != null && redisToken.equals(token);
}
}