🚩概要
- token :
本质是验证身份的令牌,一般由用户通过账户密码登录后,服务端把这些凭证通过加密等一些列操作后得到的字符串。 - token 登录流程:
- 客户端用账户密码请求登录;
- 服务端接收请求,验证账户密码;
- 验证成功后,服务端发送token给客户端;
- 客户端接收到token后保存,可以存储于sessionstorage或localstorage;
- 客户端每次请求,需要将携带token发送给服务端;
- 服务端接收请求,验证token,验证成功则响应请求返回请求数据;
- token 验证优点:
- token 存储于客户端,不会对服务端造成压力,即便是服务端集群,也不会增加维护成本;
- token 在前端可以不保存于 Cookie 中,避免CSRF攻击,提升数据的安全性;
- token 下发后,在有效期内长久生效,服务端想回收 token 权限非常困难;
✌️步骤:
1.demo构建
- 前端:采用 token + localStorage + vuex 做令牌存储验证,包含 axios 二次封装、路由守卫、api 模块化等操作;
- 后端:采用👉 mock.js 请求模拟,模拟登录接口测试数据获取等 ;
通过vueCLI脚手架搭建,包含以下基本结构:
2.后端Mock
mock 文件夹下新建 index.js,编写登录与数据获取测试接口以便后面模拟请求调取,注意需要在 main.js 引入
const Mock = require('mockjs');
// 登录接口
Mock.mock('/login', 'post', (option) => {
// 解析请求体 body 中数据
let response = JSON.parse(option.body);
return {
status: 200,
message: '请求成功',
data: response,
token: 'authorization-xxxxxx' // 模拟后端返回 token
}
})
// 数据请求模拟
Mock.mock('/data','get',(option)=> {
return {
status: 200,
message: "请求成功",
data: [1,2,3,4,5]
}
})
main.js
3、login.vue
<template>
<div>
<input type="text" v-model="form.username" placeholder="用户名">
<input type="password" v-model="form.password" placeholder="密码">
<button @click="login">登录</button>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { Login } from '../api/api.js'
export default {
name: 'Login',
data() {
return {
form: {
username: '',
password: ''
},
token: ''
}
},
methods: {
...mapMutations(['setToken']),
login() {
if(this.form.username === '' || this.form.password === '') {
alert('账号密码不能为空');
}else {
let form = new FormData();
form.append('username', this.form.username);
// 密码一般要加密处理,根据项目需求而定
form.append('password', this.form.password);
Login(form).then(res => {
console.log(res);
this.token = 'Bearer' + res.data.token;
this.setToken({token: this.token});
this.$router.push('/home');
alert('登录成功');
}).catch( err =>{
alert('账号密码错误');
console.log(err)
})
}
}
}
}
</script>
</script>
4、home.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<button @click="getData">获取数据</button>
<button @click="clearToken">清除token</button>
</div>
</template>
<script>
import { getData } from '@/api/api';
export default {
name: "Home",
data() {
return {
msg:'数据等待获取'
}
},
methods: {
getData() {
getData().then(res => {
console.log(res)
this.msg = res.data.data
})
},
clearToken() {
localStorage.removeItem('token')
}
}
};
</script>
5、路由router
添加前置路由守卫,访问其他页面需携带 token 并进行验证
import Vue from "vue";
import VueRouter from "vue-router";
const home = () => import("@/components/Home.vue");
const login = () => import("@/components/Login.vue");
Vue.use(VueRouter);
const routes = [
{
path: "/",
redirect: "/login"
},
{
path: "/login",
name: "login",
component: login
},
{
path: "/home",
name: "home",
component: home
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
/**
* 重写 router.prototype.push 避免同时跳转相同路径报错
*/
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch(err => err)
}
// 前置路由守卫
router.beforeEach( (to, from, next) => {
if(to.path === '/login') {
next();
}else {
let token = localStorage.getItem('token');
if(token === null || token === '') {
next('/login')
}else {
next()
}
}
})
export default router;
6、vuex存储
token 登录获取到后,一般要本地 localStorage 和 vuex 中存一份, 存 vuex 目的是用于需要授权接口调用,存入 vuex 便于统一管理;localStorage 数据是存放在硬盘中, vuex 数据是存储内存中读取速度更快。
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
// 存储token
token: localStorage.getItem("token") ? localStorage.getItem("token") : ""
},
mutations: {
// 修改token ,并将token 存入localStorage
setToken (state, user) {
state.token = user.token;
localStorage.setItem("token",user.token);
}
},
});
7、axios 二次封装
一般大型项目都需要对 axios 二次封装,以便请求统一处理与接口模块化管理
import router from "@/router";
import axios from "axios"
import qs from "qs"
// 配置开发&生产环境接口,根据 node 环境变量来进行判断
const devBaseURL = '/';
const proBaseURL = 'http://prod.xxxx';
const baseURL = process.env.NODE_ENV === "development" ? devBaseURL : proBaseURL;
const instance = axios.create({
baseURL: baseURL,
timeout: 5000, // 设置超时时间
withCredentials: true // 设置是否允许跨域传递的 cookie 携带凭证
})
// 配置请求参数传递格式,默认是JSON格式,根据服务器决定
instance.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
instance.defaults.transformRequest = data => qs.stringify(data)
// 配置 axios 请求拦截器, 配置 token 登录认证
instance.interceptors.request.use(
config => {
// 配置每次发送请求之前判断是否存在 token,存在则在请求头 header 上添加 token,
let token = localStorage.getItem('token');
token && (config.headers.Authorization = token);
return config;
},
error => {
return Promise.reject(error)
}
)
// 配置 axios 响应拦截器
instance.interceptors.response.use(
// 判断返回状态码,进行对应的数据返回与异常抛出操作
response => {
if(response.status === 200) {
return Promise.resolve(response)
}else {
return Promise.reject(response)
}
},
// 配置服务器状态码不是200的情况
error => {
if(error.response) {
switch(error.response.status) {
// 401: 未登录
case 401:
localStorage.removeItem('token');
alert('连接超时,请重新登录');
router.push({path: '/'});
break
// 403: 登录过期
case 403:
alert('登录过期,请重新登录');
localStorage.removeItem('token');
router.push({path: '/'});
break
// 404: 请求不存在
case 404:
alert('网络请求不存在');
break
// 500: 服务错误
case 500:
alert('网络请求有误');
default:
alert('服务错误');
}
//return Promise.reject('服务错误')
}else {
// 配置服务器没有返回结果情况
if(!window.navigator.onLine) {
// 断网情况,进行断网处理
return
}
return Promise.reject(error)
}
}
)
export default instance
8、api.js
对接口模块化处理,方便管理调用文章来源:https://www.toymoban.com/news/detail-420362.html
import request from '../utlls/request'
export function Login(params){
return request ({
method: 'post',
url: '/login',
data: params
})
}
export function getData(params) {
return request({
method: 'get',
url: '/data',
params
})
}
✔️测试
- 第一登录后,打印请求结果,可看到模拟请求返回数据中 token 字段
- 登录后,点击‘获取数据’按钮,打印请求结果,可看到请求头 Authorization 已包含 token
- 点击‘清除token’按钮,刷新页面则会自动退回登录界面
至此登录 demo 完成,若有问题欢迎指正,编写不易还望三连!😘😘😘文章来源地址https://www.toymoban.com/news/detail-420362.html
到了这里,关于token + localstorage 验证登录(vue)详细教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!