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);
  }
);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
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);
}
  • 1.
  • 2.
  • 3.
  • 4.

通过@requestheader map<string,object> header 来获取请求头,并且打印出来。

2.3 前端请求

我们在学生信息管理页面新加一个按钮,来触发这个按钮。

微服务和vue入门教程(13): token验证-zuul拦截与验证_请求头

<el-button type="primary" @click="testtoken">测试token</el-button>
  • 1.
testtoken(){
  this.$axios.get('/user/token/test');
},
  • 1.
  • 2.
  • 3.
2.4 验证

当我们触发这个接口按钮时,打开后端my-user的日志,不出问题的话,打印出了请求头。我们往后拉,其中有我们加入的authorization字段。证明我们成功在请求头中加入了token值。当然,可以删除main.js中的请求拦截代码,试试后端打印出来的请求头里还带不带token。

微服务和vue入门教程(13): token验证-zuul拦截与验证_filter_02

3. 后端zuul修改

新建filter和util文件,tokenutil.java直接从my-user微服务中负责过来就好。

微服务和vue入门教程(13): token验证-zuul拦截与验证_java_03

记得在pom文件中加入jwt依赖。

<dependency>
    <groupid>com.auth0</groupid>
    <artifactid>java-jwt</artifactid>
</dependency>
  • 1.
  • 2.
  • 3.
  • 4.

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;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.

4. 验证

重启zuul,访问后端的接口,如果不出问题的话,zuul控制台中可以打印出下面的日志来。

微服务和vue入门教程(13): token验证-zuul拦截与验证_filter_04

补:

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;
        }
    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.