Vue 实现携带 Token 免密登录验证 ——Token使用(二)

7,193

前言

看文章之前,强烈建议先把项目拉取下来!案例来自小弟的开源项目,这是 Token 免密登录验证的前端实现。「项目Github」

文章内容只是个人学习的一些总结经验,不具有权威性,强烈建议先移步:NodeJS(Express框架)实现 Token 验证免密登录 (一)

Token 免密登录前端原理

在用户第一次登录成功的时候,后端会返回一个 Token,这个值Token 主要的作用就是用于识别用户的身份。相当于账号密码。正常情况下,前端给后端发送请求的时候,后端都需要先判断用户的身份,来返回相应的数据给用户。但我们不可能每次请求的时候都要用户输入一次账号和密码。为了便于理解,你可以看成 Token ≈ 用户输入账号和密码 (当然这不太严谨)。获取到Token后,你需要把 Token 存在 Cookie中。接着向服务器发送请求时,你从 Cookie 中取出 Token,在请求头中携带上 Token ,就搞定了!

还可以用 vue-router 提供的beforeEach方法配合 Token进行简单的权限控制。例如:Token过期跳转到登录页。后面说权限控制的时候再写。

安装 js-cookie 和 安装 axios (http库)

js-cookie一个简化 cookie增删改查的 JS 库,

//安装js-cookie
npm i js-cookie -S 

//安装axios
npm i axios -S 

js-cookie 和 axios 的使用比较简单,就不详细说明和例子一起看。详细文档:「js-cookie」「axios」

登录并获取 Token

我们直接看例子

import Cookies from "js-cookie";
import { adminLogin } from "@/api/api";

submit() {
      this.$refs.form.validate(async (valid) => {
        // valid 为 false 时,表单校验通过(element-ui Form组件)
        if (!valid) return;
        //调用登录接口,并把用户的账号密码传给后端
        let res = await adminLogin(this.loginForm);
        if (res.code !== 0) {
          this.$message.error(res.msg);
        } else {
          //在返回的结果中获取到 token,并存放在 Cookie 中
          //Cookies.set(key,data) 是 `js-cookie`提供的存放 Cookie 的方法  
          Cookies.set("token", res.data.token); 
          //Cookies.set("token", res.data.token, { expires: 7 });
          //这里可以设置一下过期时间,最好比后端规定的时间早
          Cookies.set("name", res.data.name);
          Cookies.set("userId", res.data.userId || "");
          Cookies.set("role", res.data.role);
          //登录成功跳转到网站首页
          this.$router.replace({ path: "/" });
        }
      });
    },

到这里我们就已经拿到 token了。

配置 Token

KiteBlog axios 一些全局的配置都存放在src\utils\request.js中,所以像Token这种几乎所有请求都需要携带的数据,放在request.js是比较合适的。

axios 提供了拦截器的功能。详细移步:拦截器。这里只用到请求拦截器「axios.interceptors.request.use()」,顾名思义,就是在发送请求前经进行拦截,然后修改请求的数据,例如:请求头(header)、body 等数据。 前面说过,Token是存在请求头中的。

axios.interceptors.request.use((config) => {
	//排除登录接口,登录是不需要 Token 的,只有登录了才能获取到 Token
    if (config.url !== "auth/adminLogin") {
        //给请求头的设置Token, Cookies.get()用于获取存放在 Cookie 的 Token
		config.headers["authorization"] = `Bearer ${Cookies.get("token")}`;
	}
    //这一步是必须的!
	return config
}, (error) => {
	return Promise.reject(error);
});

这样就搞定了,是不是很简单

Token 保存在哪里比较合适? Cookie?sessionstorage?还是 localstorage ?

特意去看了一下 cookie、sessionstorage、localstorage 的特性

失效时间对比:

cookie:在不设置过期时间的时候,关闭浏览器就会进行清除。如果设置了过期时间,将以过期时间为准

sessionstorage:关闭浏览器就会进行清除,不可以设置过期时间

localstorgae:不手动清除将一致保存在浏览器中,不可以设置过期时间

储存大小对比(不同浏览器存在差异):

cookie:一般为 4k

localStorage:一般为5M

sessionStorage:一般为5M

总结:

每次请求的时候,浏览器会自动携带上 cookie 的数据,localStorage 和 sessionStorage 则不会。

从长度限制和带宽流量占用的角度来看:cookie 确实属于劣势

补充:安全性:token 存放在 cookie 中,请求的时候会自动带上cookie的信息,可能会招到 CSRF攻击,需要做好 CSRF 防御。服务器验证token时,最好取header的token,而不是为直接取cookie的信息。或者改用localStorage。

但是从设置过期时间以及免密登录的角度来考虑,cookie 要比 sessionstorag 和 localstorgae 稍微方便一些。我们可以直接判断 cookie 有没有 token ,如果有直接进入网站管理后台,而无需再次跳转到登录页,让用户输入密码。

这是说的过期是指,token 储存在浏览器 cookie 中的过期时间, 并不是 token 在后端的真正时间。 设置浏览器 cookie 过期时间是为了方便前端使用而已。

对于前端来说,最好办法就是后端但把 token 放在 cookie 里,前端不用处理,哈哈