jjwt的jar包引入
fastjson的jar包引入
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
用户登陆成功后生成 token 返给前端进行缓存
package com.baojian.zhang.util;
import java.util.Date;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class TokenUtil {
//这里是加密解密的key。
public static String tokenKey = "MiTMW2toifJyH0MO";
/**
* 根据用户卡号生成token,默认有效期为1个月
* @param expiresDate 过期时间
* @param cardNumber
* 用户卡号
* @return token
*/
public static String createToken(String cardNumber, Date expiresDate) {
// 生成token
return Jwts.builder().setSubject(cardNumber).setIssuedAt(new Date())// 设置签发时间
.setExpiration(expiresDate)// 设置过期时间
.signWith(SignatureAlgorithm.HS512, tokenKey).compact();
}
/**
* 检验token是否可用
*
* @param token
* @return 可用返回true,否则返回false
*/
public boolean checkToken(String token) {
try {
Jwts.parser().setSigningKey(tokenKey).parseClaimsJws(token);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
当用户登录成功后,访问接口时进行 token 校验。本文章把校验放在 Zuul 进行统一校验
package com.baojian.zhang.filter;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import com.alibaba.fastjson.JSON;
import com.baojian.zhang.base.BaseVO;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
public class TokenFilter extends ZuulFilter {
@Override
public boolean shouldFilter() {
// 过滤含有 sign 的接口
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
ctx.set("startTime", System.currentTimeMillis());// 设置请求开始时间
// 获取 sign 参数
String sign = request.getParameter("sign");
if (StringUtils.isNotEmpty(sign)) {
return true;
}
return false;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
// 获取 sign 参数
String sign = request.getParameter("sign");
// 有sign 时必须传入卡号,检查卡号是否存在
String cardNumber = request.getParameter("cardNumber");
if (StringUtils.isEmpty(cardNumber)) {
returnResponse(ctx, JSON.toJSONString(new BaseVO<Void>(2, "卡号不能为空")));
return null;
}
// 检查token是否过期
try {
Jws<Claims> jws = Jwts.parser().setSigningKey("MiTMW2toifJyH0MO").parseClaimsJws(sign);
if (!cardNumber.equals(jws.getBody().getSubject())) {
returnResponse(ctx, JSON.toJSONString(new BaseVO<Void>(101, "用户卡号与token不匹配!")));
return null;
}
} catch (ExpiredJwtException e) {
// token已过期
returnResponse(ctx, JSON.toJSONString(new BaseVO<Void>(105, "token已过期,请重新登录!")));
return null;
} catch (UnsupportedJwtException e) {
// token不支持
returnResponse(ctx, JSON.toJSONString(new BaseVO<Void>(107, "token信息不能被解析,请重新登录!")));
return null;
} catch (MalformedJwtException e) {
// token格式不对
returnResponse(ctx, JSON.toJSONString(new BaseVO<Void>(106, "token格式错误,请重新登录!")));
return null;
} catch (SignatureException e) {
// token签名不对
returnResponse(ctx, JSON.toJSONString(new BaseVO<Void>(104, "token签名错误,请重新登录!")));
return null;
} catch (IllegalArgumentException e) {
// token格式转换错误
returnResponse(ctx, JSON.toJSONString(new BaseVO<Void>(108, "token为空,请重新登录!")));
return null;
}
// 这里return的值没有意义,zuul框架没有使用该返回值
return null;
}
@Override
public String filterType() {
/**
* pre:可以在请求被路由之前调用
* route:在路由请求时候被调用
* post:在route和error过滤器之后被调用
* error:处理请求时发生错误时被调用
*/
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return 0;
}
private void returnResponse(RequestContext ctx, String body) {
ctx.getResponse().setHeader("Content-Type", "application/json;charset=UTF-8");
ctx.getResponse().setCharacterEncoding("UTF-8");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(200);
ctx.setResponseBody(body);
}
}
将TokenFilter加入到请求拦截队列,在启动类中添加以下代码:
package com.baojian.zhang;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import com.baojian.zhang.filter.TokenFilter;
@SpringBootApplication
@EnableZuulProxy
public class MyZuulServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MyZuulServiceApplication.class, args);
}
@Bean
public TokenFilter tokenFilter() {
return new TokenFilter();
}
}