1. 前言

对于身份验证,传统来说,我们使用的是session。但是使用session会增加服务器的压力,并且不适合于今日的分布式集群开发。于是我们倾向于使用token。

1、Token的引入:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。

2、Token的定义:Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

3、使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。

作者:9264oo
链接:https://www.jianshu.com/p/24825a2683e6
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 1.
  • 2.
  • 3.
  • 4.

2. 后端编写token

我们要使用JWT来生成token,因此我们需要引入JWT依赖。

2.1 加入依赖

在父pom和user微服务的pom文件中加入(user的pom里不要带版本号)

<!--jwt-->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.8.3</version>
</dependency>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
2.2 编写token代码

在user微服务中src/main/java/com.user新建utl文件夹,在此新建TokenUtil.java文件

package com.user.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.

里面有生成的方法和检测的方法。

2.3 修改UserController文件login方法
public JSONObject login(@RequestBody JSONObject jsonObject){

    //数据库进行检查
    User user = userService.login(jsonObject);

    JSONObject result = new JSONObject();
    //若正确返回200,若错误返回400
    if(user == null){
        result.put("state",400);
    }else {
        String token = TokenUtil.sign(jsonObject.getString("userName"));
        System.out.println(token);
        result.put("state",200);
        result.put("token",token);
    }
    return  result;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

其实对比来看,只是添加了

String token = TokenUtil.sign(jsonObject.getString("userName"));
 result.put("token",token);
  • 1.
  • 2.

生成token,将token传到前端

3. 前端引入Vuex,编写store文件

我们需要建一个文件,来保存token信息,来作为一个全局变量,于是vue的store上场了。store需要用的Vuew,因此我们需要先下载Vuex。

3.1 下载Vuex
npm install vuex --save
  • 1.
3.2 新建store

在 src 目录下新建一个文件夹 store,并在该目录下新建 index.js。在这个文件中,我们来保存全局变量。

可以看到,我们保存了三个变量:userName,Authorization,signTime。

其中userName就是用户登录时的用户名,Authorization保存的是token,这是http请求头中的一个关键字。

signTime:我们保存的是token的生成时间,未来我们将在前端来验证token是否过期。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

const store =  new Vuex.Store({
  state: {
      userName: window.localStorage.getItem('userName') ? window.localStorage.getItem('userName') : '',
      Authorization: window.localStorage.getItem('Authorization') ? window.localStorage.getItem('Authorization') : '',
      signTime: window.localStorage.getItem('signTime') ? window.localStorage.getItem('signTime') : '',

  },
  mutations: {
    loginChange (state, user) {
      state.userName = user.userName;
      state.Authorization = user.Authorization;
      state.signTime = user.signTime;

      window.localStorage.setItem('userName', state.userName);
      window.localStorage.setItem('Authorization', state.Authorization);
      window.localStorage.setItem('signTime', state.signTime);
    }
  }
});
 export default store;
  • 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.
3.3 修改main.js代码

加入以下代码

import Vuex from 'vuex'
import store from './store'
  • 1.
  • 2.
Vue.use(Vuex);
  • 1.
new Vue({
  el: '#app',
  router,
  // 注意这里哦
  store,
  components: { App },
  template: '<App/>'
})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
3.4 修改login.vue
<script>
//引入vuex
  import {mapMutations} from 'vuex';
  export default {
    name: 'Login',
    // 绑定的数据
    data() {
      。。。。。。
      。。。。。。
    },
    methods:{
    // 引入loginChange方法
      ...mapMutations(['loginChange']),
      login(){
        this.$axios.post('/user/login', {
            userName: this.loginForm.userName,
            passWord: this.loginForm.password
          })
          .then(successResponse =>{
            //获取后端返回数据
            let state = successResponse.data.state;
            //打印token
            console.log(successResponse.data.token);
            //判断是否登录成功
            if(state === 200){
            // 加入到全局变量中
              this.loginChange({
                userName: this.loginForm.userName,
                Authorization: successResponse.data.token,
                signTime: new Date().getTime()
              });
              this.$router.push('/home');
            }else {
              this.$message("用户名或密码错误");
            }
          })
      }
    }
  }
</script>
  • 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.

4. 测试

运行后端服务,以及打开登录界面,进行登录

微服务和VUE入门教程(9): token验证-token后端生成以及前端获取_微服务


第三行的长字符串就是生成的token

微服务和VUE入门教程(9): token验证-token后端生成以及前端获取_用户名_02


前端控制台打印的字符串就是从后端传过来的token信息。