微服务和VUE入门教程(13): token验证-zuul拦截与验证
微服务和VUE入门教程(0): 着手搭建项目
微服务和VUE入门教程(1): 搭建前端登录界面
微服务和VUE入门教程(2): 注册中心
微服务和VUE入门教程(3): user微服务的搭建
微服务和VUE入门教程(4):网关zuul的搭建
微服务和VUE入门教程(5): 前后端交互
微服务和VUE入门教程(6):连接数据库-mybatis
微服务和VUE入门教程(7):配置中心-config
微服务和VUE入门教程(8):前端主页的编写
微服务和VUE入门教程(9): token验证-token后端生成以及前端获取
微服务和VUE入门教程(10): token验证-前端登录拦截以及token过期提醒
微服务和VUE入门教程(11): mybatis 动态查询
微服务和VUE入门教程(12):前端提示搜索框的实现
微服务和VUE入门教程(13): token验证-zuul拦截与验证
微服务和VUE入门教程(14): 热部署
微服务和VUE入门教程(15): 课堂小知识
微服务和VUE入门教程(16): zuul 熔断
微服务和VUE入门教程(17): VUE 响应拦截器
微服务和VUE入门教程(18): 前端接口模块化
微服务和VUE入门教程(19): VUE组件化–子组件向父组件通信
微服务和VUE入门教程(20): VUE组件化–父组件向子组件通信
微服务和VUE入门教程(21): springboot中定时器-Schedule
微服务和VUE入门教程(22): 页面长时间未操作自动退出登录
微服务和VUE入门教程(23): 微服务之间的调用
微服务和VUE入门教程(24): 微服务之断路器
微服务和VUE入门教程(25): 微服务之Hystrix-dashboard
微服务和VUE入门教程(26): 微服务之turbine
微服务和VUE入门教程(27):VUE前端工程打包
1. 前言
对于后端的一些接口,有时候,我们不希望没有登录的人员访问,或者说,不希望没经过授权的人员访问。因此,我们可以在zuul这里,加一个过滤器,来验证请求头里是否带有合格的token。如果带有合格的token,说明访问者是合法登录使用人员,如果没有token或者token不合格,则不让他访问接口。
2.前端编写
2.1 请求拦截器
在main.js代码中加入下面代码。拦截向后端发送的http请求,在请求头里面,加入token(Authorization)。
//请求拦截器
axios.interceptors.request.use(
//请求头加入token
config =>{
if(localStorage.getItem('Authorization')){
config.headers.Authorization = localStorage.getItem('Authorization');
}
console.log(config);
return config;
},
error => {
return Promise.reject(error);
}
);
2.2 后端验证代码
为了验证,我们加的请求拦截器是否真的生效,真的把token值加入到请求头里。我们在后端尝试打印一下请求头。修改my-user的UserController.java文件
@RequestMapping(value = "/token/test", method = RequestMethod.GET)
public void testToken(@RequestHeader Map<String,Object> header){
System.out.println(header);
}
通过@RequestHeader Map<String,Object> header 来获取请求头,并且打印出来。
2.3 前端请求
我们在学生信息管理页面新加一个按钮,来触发这个按钮。
<el-button type="primary" @click="testToken">测试token</el-button>
testToken(){
this.$axios.get('/user/token/test');
},
2.4 验证
当我们触发这个接口按钮时,打开后端my-user的日志,不出问题的话,打印出了请求头。我们往后拉,其中有我们加入的authorization字段。证明我们成功在请求头中加入了token值。当然,可以删除main.js中的请求拦截代码,试试后端打印出来的请求头里还带不带token。
3. 后端zuul修改
新建filter和util文件,TokenUtil.java直接从my-user微服务中负责过来就好。
记得在pom文件中加入JWT依赖。
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
ZuulTokenFilter.java
package com.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.zuul.util.TokenUtil;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class ZuulTokenFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
/**
* 判断请求的接口是否需要验证token
* 在这里,我们设定 /api/user/login,不需要验证token
* 若不需要验证,返回false,
* 需要验证,返回true
*
*/
@Override
public boolean shouldFilter() {
//1. 获取Zuul提供的请求上下文对象
RequestContext requestContext = RequestContext.getCurrentContext();
// 获取request对象
HttpServletRequest request = requestContext.getRequest();
if("/api/user/login".equals(request.getRequestURI())){
return false;
}else if(request.getMethod().equals("OPTIONS")){
return false;
}else {
return true;
}
}
/**
* 若shouldFilter返回true,则运行run方法,来验证token
* */
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
// 获取token值
String token = request.getHeader("authorization");
System.out.println(token);
// 判断是否为空
if(token == null || "".equals(token.trim())){
//没有token,验证失败
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}else {
try {
//验证token是否合格
boolean tokenVerify = TokenUtil.verify(token);
//如果token合格,根据请求,寻找路由
if(tokenVerify){
requestContext.setSendZuulResponse(true);
}else {
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
}catch (Exception e){
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
}
return null;
}
}
4. 验证
重启zuul,访问后端的接口,如果不出问题的话,zuul控制台中可以打印出下面的日志来。
补:
TokenUtil.java
package com.zuul.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Date;
public class TokenUtil {
private static final long EXPIRE_TIME = 24*60*60*1000; //有效时长
private static final String TOKEN_SECRET = "ben"; // 秘钥
/**
* 签名 生成
* @parm userName
* */
public static String sign(String userName){
String token = null;
try {
Date expiresAt = new Date(System.currentTimeMillis()+EXPIRE_TIME);
token = JWT.create()
.withIssuer("auth0")
.withClaim("userName",userName)
.withExpiresAt(expiresAt)
//使用HMAC256算法加密
.sign(Algorithm.HMAC256(TOKEN_SECRET));
}catch (Exception e){
e.printStackTrace();
}
return token;
}
/**
* 签名验证
* @param token
* */
public static boolean verify(String token){
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET))
.withIssuer("auth0").build();
DecodedJWT jwt = verifier.verify(token);
System.out.println("认证通过");
System.out.println("userName:"+jwt.getClaim("userName").asString());
System.out.println("过期时间:"+jwt.getExpiresAt());
return true;
}catch (Exception e){
return false;
}
}
}