token验证登录逻辑流程

  1. 客户端使用用户名跟密码请求登录。

  2. 服务端收到请求,去验证用户名与密码。

  3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端

  4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里

  5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token

  6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

1、创建token工具类,用来生成token 与验证token。

public class TokenUtil {
    private static String key = "asdfsdfhjhiqehshdjasznxbczgajoisaud";
    private static SecretKey secretKey = new SecretKeySpec(key.getBytes(), SignatureAlgorithm.HS256.getJcaName()); //设置JWT密钥

    public static String createToken(User user) {
        //生成token
        long currentTimeMillis = System.currentTimeMillis();
        HashMap<String, Object> map = new HashMap<>();
        map.put("id", user.getId());
        String token = Jwts.builder()     //创建JWT对象
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date(currentTimeMillis))
                .setClaims(map)
                .signWith(secretKey)
                .compact();//生成token
        return token;
    }

    public static int verifyToken(String token) {
        //验证token
        try {
            Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
            return 0;
        } catch (ExpiredJwtException e) {  //过期JWT异常
            return 1;
        } catch (UnsupportedJwtException e) {  //不支持JST异常
            return 2;
        } catch (MalformedJwtException e) {  //格式不正确的JWT
            return 3;
        } catch (IllegalArgumentException e) { // 非法数据异常
            return 4;
        }
    }

    public static Map<String, Object> parseToken(String token) {
        Map<String, Object> body = Jwts.parser()  //得到DefaultJwtParser
                .setSigningKey(secretKey)  //设置签名密钥
                .parseClaimsJws(token)
                .getBody();
        return body;
    }

2、登录进行账号密码的验证,验证成功,生成token传回前端。

@ApiOperation("用户登录")
@PostMapping("/login")
public Result login(@RequestBody LoginForm loginForm, HttpSession session){
    User user = userService.login(loginForm);
    if (user != null){
        session.setAttribute("user",user);
        String token = TokenUtil.createToken(user);
        JSONObject jo = new JSONObject();
        jo.put("user",user);
        jo.put("token",token);
        return new Result(GET_OK,jo,"登录成功");
    }else {
        return new Result(GET_ERR,null,"账号或密码错误");
    }
}

3、前端进行

        前端主要操作就是存储后端传过来的token,将token保存,然后每次发起请求的时候都携带token回去后端,让后端进行校验。

Vue实现

1、登录成功获取到后端传过来的token值,然后将值传入vuex中进行存储 login.vue

//导入函数
...mapMutations(['changeLogin']),
login(forName) {
  const  $message = this.$message
  const _this = this
  this.$refs[forName].validate((valid) => {
    if (valid) {
      axios.post('http://localhost:8081/user/login',this.ruleForm).then(function (resp){
        console.log(resp)
        if (resp.data.code == 20041){
          $message.success({
            message:'登录成功',
            offset:100,
          })
          //将用户token保存到vuex中
          _this.changeLogin({Authorization:resp.data.data.token})
          _this.$router.push('/userManger')
        }
        if (resp.data.code == 20040){
          _this.$alert(resp.data.msg,'提示',{
            confirmButtonText:'确定',
          })
        }
      })
    }
  })
},

2、vuex中的操作 store/index.js

export default new Vuex.Store({
  //统一定义公共数据(类似于data()return)
  state: {
    //存储token
    Authorization:localStorage.getItem('Authorization')? localStorage.getItem('Authorization') : ''
  },
  //类似于computed(计算属性,对现有的状态进行计算得到新的)
  getters: {

  },
  //修改数据
  mutations: {
    //修改token,并将token存入localStorage
    changeLogin(state,user){
      state.Authorization = user.Authorization;
      localStorage.setItem('Authorization',user.Authorization);
    }
  },
  //发起异步请求
  actions: {
  },
  //模块拆分
  modules: {
  }
})

3、设置请求拦截 让每个请求在请求头中都携带token main.js

//请求拦截器
axios.interceptors.request.use(config => {
        if (localStorage.getItem('Authorization')) {
            config.headers.Authorization = localStorage.getItem('Authorization');
        }
        return config
    },error =>{
        return Promise.reject(error);
    }
);

4、设置路由守卫 router/index.js

//导航守卫
router.beforeEach((to,from,next)=>{

  if (to.path === '/login'){
    next();
  }else {
    const  token = localStorage.getItem("Authorization") //获取token
    //token不存在
    if(token === null || token === ''){
      alert('请先登录!!!')
      next('/login');
    }else {
      next();
    }
  }
})

4、后端进行

后端设置拦截器

protected void addInterceptors(InterceptorRegistry registry) {
    //放行路径
    String[] excludePatterns = new String[]{"/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**",
            "/api", "/api-docs", "/api-docs/**", "/doc.html/**"};

    //添加拦截路径
    registry.addInterceptor(userInterceptor)
            .addPathPatterns("/user/**")
            .excludePathPatterns("/user/login");
}
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    if ((request.getMethod().toUpperCase().equals("OPTIONS"))) {
        return true;
    }
    String token = request.getHeader("Authorization");

    if (token == null){
        throw  new LoginException("请先登录");
    }else {
        int i = TokenUtil.verifyToken(token);
        if (i == 0){
            return true;
        }else {
            throw  new LoginException("请重新登录");
        }
    }
}

Logo

前往低代码交流专区

更多推荐