vue项目登录及token验证 vue-ant

在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下:

1、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码

2、后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token

3、前端拿到token,将token存储到localStorage和vuex中,并跳转路由页面

4、前端每次跳转路由,就判断 localStroage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面

5、每次调后端接口,都要在请求头中加token

6、后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401

7、如果前端拿到状态码为401,就清除token信息并跳转到登录页面

.
.
.
.
实操代码:

1.login页(账号密码登录完成后,将后台返回的token储存到本地);最后附上了登录页完整代码

handleSubmit(e) {var that = this;this.userName = this.userName.trim();this.password = this.password.trim();if (this.userName === "" && this.password === "") {that.$message.warning("账号和密码无内容");return;}if (this.userName === "") {that.$message.warning("账号无内容");return;}if (this.password === "") {that.$message.warning("密码无内容");return;}var username = document.getElementById("username").value;var password = document.getElementById("password").value;e.preventDefault();this.form.validateFields((err, values) => {//这一步将用户名储存在vuex ||||||||||目前域账号和用户名都是写一样了||||||||||||||||||||||||||||||||||||||||||||||||axios.post(this.$store.state.windowCONTENT + "sysConfig/getUserRole", {loginUser: this.userName,}).then((res) => {if (res.data.success == 0) {//有权限this.$store.state.loginUser = this.userName;this.$store.state.userName = this.userName;this.$store.state.roleCode = res.data.data.roleCode;//存入tokenlocalStorage.setItem("token",JSON.stringify(res.data.data.token));// console.log(res.data.data,this.$store.state.roleCode);if (!err) {this.$router.push("/layout");this.$message.success("登陆成功");}} else {//无权限this.$message.error(res.data.data);}});});},

2.marn.js(配置请求拦截器,每次请求携带token,后端进行验证;配置响应拦截器,根据后端验证返回的结果,判断token是否过期)

import "babel-polyfill";
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import { Button, message } from 'ant-design-vue';
import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.css";
import zh_CN from "ant-design-vue/lib/locale-provider/zh_CN";
import moment from "moment";
import "moment/locale/zh-cn";
import "./assets/iconfont/iconfont";
import axios from "axios";Vue.component(Button.name, Button);Vue.config.productionTip = false;Vue.use(Antd);
Vue.prototype.$message = message;// 设置axios全局默认的BASE-URL, 只要设置了全局的默认base_url,以后的请求会自动拼接上base_url
//axios.defaults.baseURL = 'http://localhost:8888/api/private/v1/'// 配置axios的请求拦截器-(每次在请求头上携带后台分配的token-后台判断token是否有效等问题)
axios.interceptors.request.use(function(config) {// 在发送请求之前做些什么// console.log('请求到了哟', config.headers.Authorization)// 统一的给config设置 tokenconfig.headers.Authorization = JSON.parse(localStorage.getItem("token"));config.headers['Token'] = JSON.parse(localStorage.getItem("token"));return config;},function(error) {// 对请求错误做些什么return Promise.reject(error);}
);//响应拦截器 与后端定义状态是100时候是错误 跳转到登录界面
axios.interceptors.response.use(function (response) {// 对响应数据做点什么console.log(response)//当返回信息为未登录或者登录失效的时候重定向为登录页面if (response.data.status == 100 || response.data.message == '用户未登录或登录超时,请登录!') {router.push({path: "/login",querry: { redirect: router.currentRoute.fullPath }//从哪个页面跳转})message.warning(response.data.message);}return response;
}, function (error) {// 对响应错误做点什么return Promise.reject(error)
})moment.locale("zh-cn");
new Vue({zh_CN,router,watch: {// 监听路由变化"$route.path": function(newVal, oldVal) {console.log(`new_path = ${newVal}, old_path = ${oldVal}`);},},store,render: (h) => h(App),
}).$mount("#app");

3.router.js(配置导航守卫,有token或者是去登录页就通过,否则定向到登录页)

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Layout from '../components/Layout.vue'
import Login from '../components/Login.vue'Vue.use(VueRouter)const routes = [{path: '/',redirect: 'login'},{path: '/login',name: 'Login',component: Login},{path: '/layout',name: 'Layout',component: Layout},{path: '/about',name: 'About',// route level code-splitting// this generates a separate chunk (about.[hash].js) for this route// which is lazy-loaded when the route is visited.component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')}
]const router = new VueRouter({routes
})// to 到哪去
// from 从哪来
// next 是否放行 next() 放行 next('/login') 拦截到登录
// 如果准备去登录, 不需要拦截
// 如果已经登录过了, 有token, 不需要拦截
// 如果不是去登陆, 且没有 token, 拦截到登录页
router.beforeEach((to, from, next) => {const token = JSON.parse(localStorage.getItem('token'));console.log(token);// console.log(to)if (to.path === '/login' || token) {next()} else {next('/login')}
})export default router

4.退出:清除本地储存的token

//退出登录signOut() {console.log("点击了退出", this.$route.query.sessionId);localStorage.clear("token");this.$route.push('/')//将vuex的数据初始化和清除默认的数据},

.
.
.
.
.
.

完整登录页

<template><div class="login"><div class="logo"><img :src="logoUrl" alt /></div><div class="welcome">WELCOME</div><div class="platform">欢迎来到XX平台</div><div class="box"><a-formid="components-form-demo-normal-login":form="form"class="login-form"@submit.prevent="handleSubmit"><a-form-item><div class="l-bor">登录</div></a-form-item><a-form-item><div class="account">账号</div></a-form-item><a-form-item><a-input v-model="userName" allowClear class="user-name" placeholder="请输入"><!-- v-decorator="['userName',{ rules: [{ required: true, message: '请输入账号名!' }] },]"--><a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)" /></a-input></a-form-item><a-form-item><div class="p-box">密码</div></a-form-item><a-form-item><!-- <a-inputv-decorator="['password',{ rules: [{ required: true, message: 'Please input your Password!' }] },]"type="password"placeholder="Password"><a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)" /></a-input>--><a-input-passwordv-model="password"allowClearclass="password"type="password"placeholder="请输入"><!-- v-decorator="['password',{ rules: [{ required: true, message: '请输入密码!' }] },]"--><a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)" /></a-input-password></a-form-item><a-form-item><!-- <a-checkboxv-decorator="['remember',{valuePropName: 'checked',initialValue: true,},]">Remember me</a-checkbox>--><!-- <a class="login-form-forgot" href>Forgot password</a> --><a-button:style="{opacity: (btnFlag ? .5 : 1)}"type="primary"html-type="submit"class="login-form-button"><spanstyle="width:58px;height:24px;font-size:17px;font-family:PingFang-SC-Light,PingFang-SC;font-weight:300;color:rgba(255,255,255,1);line-height:24px;text-shadow:0px 2px 3px rgba(62,32,201,0.1);">登录</span></a-button><!-- Or --><!-- <a href>register now!</a> --></a-form-item></a-form></div><div class="bottom"></div></div>
</template><script>
import axios from "axios";
export default {data() {return {logoUrl: require("../assets/logo.svg"),userName: "",password: "",btnFlag: true,flagColor: {opacity: 0.5,},};},beforeCreate() {this.form = this.$form.createForm(this, { name: "normal_login" });},created() {},methods: {handleSubmit(e) {var that = this;this.userName = this.userName.trim();this.password = this.password.trim();if (this.userName === "" && this.password === "") {that.$message.warning("账号和密码无内容");return;}if (this.userName === "") {that.$message.warning("账号无内容");return;}if (this.password === "") {that.$message.warning("密码无内容");return;}// jucenter.submit({name:this.userName,pwd:this.password});e.preventDefault();this.form.validateFields((err, values) => {//这一步将用户名储存在vuex ||||||||||目前域账号和用户名都是写一样了||||||||||||||||||||||||||||||||||||||||||||||||console.log(this.userName, this.password);axios.post(this.$store.state.windowCONTENT + "sysConfig/getUserRole",{loginUser: this.userName}).then(res => {if (res.data.success == 0) {//有权限this.$store.state.loginUser = this.loginUser;this.$store.state.userName = res.data.data.userName;this.$store.state.roleCode = res.data.data.roleCode;//存入tokenlocalStorage.setItem("token",JSON.stringify(res.data.data.token));if (!err) {this.$router.push("/layout");console.log(111);this.$message.success('登陆成功')}} else {//无权限this.$message.error(res.data.data)}})});},},watch: {userName: function (v1, v2) {var that = this;if (v1 && this.password) {this.btnFlag = false;console.log(this.btnFlag);} else {this.btnFlag = true;console.log(this.btnFlag);}},password: function (v1, v2) {var that = this;if (v1 && this.userName) {this.btnFlag = false;console.log(this.btnFlag);} else {this.btnFlag = true;console.log(this.btnFlag);}},},
};
</script>
<style   lang="less">
.login {position: relative;text-align: left;height: 100%;background: linear-gradient(154deg,rgba(119, 182, 244, 1) 0%,rgba(66, 106, 229, 1) 100%);// background-color: pink!important;// overflow: hidden;.logo {position: absolute;top: 21px;left: 35px;}.welcome {position: absolute;bottom: 60%;left: 10%;width: 416px;height: 100px;font-size: 72px;font-family: PingFang-SC-Regular, PingFang-SC;font-weight: 400;color: rgba(255, 255, 255, 1);line-height: 100px;letter-spacing: 6px;}.platform {position: absolute;bottom: 53%;left: 10%;width: 313px;height: 33px;font-size: 24px;font-family: PingFang-SC-Light, PingFang-SC;font-weight: 300;color: rgba(255, 255, 255, 1);line-height: 33px;letter-spacing: 2px;}.box {position: absolute;bottom: 10%;right: 0;// margin: 0 auto;// margin-bottom: 151px; //定位高度-----↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓margin-right: 21%;width: 370px;height: 500px;border-radius: 10px;background: rgba(252, 251, 255, 1);padding: 0px 53px;//去除默认下边距.ant-form-item {margin-bottom: 0;}//输入框.ant-input-affix-wrapper .ant-input:not(:last-child) {height: 36px;font-size: 14px;font-family: PingFang-SC-Regular, PingFang-SC;font-weight: 400;color: rgba(53, 58, 64, 1);// background-color: pink;}//登录按钮#components-form-demo-normal-login .login-form-button {width: 264px;height: 44px;background: linear-gradient(90deg,rgba(60, 163, 247, 1) 0%,rgba(28, 106, 235, 1) 100%);box-shadow: 0px 2px 3px 0px rgba(62, 32, 201, 0.1);border-radius: 6px;}.l-bor {margin-left: -53px;margin-top: 50px;line-height: 25px;border-left: 6px solid rgba(28, 106, 235, 1);padding-left: 47px;font-size: 18px;font-family: PingFang-SC-Medium, PingFang-SC;font-weight: 500;color: rgba(53, 58, 64, 1);letter-spacing: 1px;}// .account{//   margin-top: 58px;//   width:27px;//   height:17px;//   font-size:12px;//   font-family:PingFang-SC-Light,PingFang-SC;//   font-weight:300;//   color:rgba(53,58,64,1);//   line-height:17px;//   letter-spacing:1px;// }.ant-form-item:nth-child(2) {position: absolute;top: 133px;.account {width: 27px;height: 17px;font-size: 12px;font-family: PingFang-SC-Light, PingFang-SC;font-weight: 300;color: rgba(53, 58, 64, 1);line-height: 17px;letter-spacing: 1px;}}.ant-form-item:nth-child(3) {position: absolute;top: 160px;width: 264px;}.ant-form-item:nth-child(4) {position: absolute;top: 230px;width: 264px;.p-box {width: 27px;height: 17px;font-size: 12px;font-family: PingFang-SC-Light, PingFang-SC;font-weight: 300;color: rgba(53, 58, 64, 1);line-height: 17px;letter-spacing: 1px;}}.ant-form-item:nth-child(5) {position: absolute;top: 257px;width: 264px;}.ant-form-item:nth-child(6) {position: absolute;top: 376px;width: 264px;}}.bottom {position: absolute;bottom: 0;width: 100%;// height: 151px; //固定高度-----↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑height: 10%; //固定高度-----↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑background: linear-gradient(360deg,rgba(75, 118, 232, 0) 0%,rgba(57, 98, 224, 0.41) 100%);}
}
#components-form-demo-normal-login .login-form {max-width: 300px;
}
#components-form-demo-normal-login .login-form-forgot {float: right;
}
#components-form-demo-normal-login .login-form-button {width: 100%;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/403874.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

广告狂人 第1季

《Mad Men/广告狂人》是由American Movie Classics公司出品的美剧。故事背景设定在上世纪六十年代的纽约&#xff0c;大胆地描述了美国广告业黄金时代残酷的商业竞争。该剧曾获得第65届、第66届、第67届美国电影电视金球奖最佳电视剧。并连续四年夺得艾美奖剧情类最佳电视剧奖。…

设置Clover默认进入Windows,按快捷键F8可选择不同的引导

系统情况&#xff1a; Win7 Mac10.9.5 Clover 我要达到的目标是&#xff1a;默认进入Windows系统&#xff0c;如果有需要&#xff0c;可以选择进入其他系统&#xff0c;如Mac OS X 我原以为可以在clover中配置&#xff0c;达到这个目标&#xff0c;可是我经过多次实践&am…

适配器和外观模式

结构型&#xff1a;Adapter与Facade&#xff08;适配器和外观模式&#xff09;   一般作为阅读材料&#xff0c;首先想要明确的是我现在了解的设计模式的初衷&#xff0c;即为了解决什么问题。 适配器&#xff0c;如果有买过港版Iphone在内地使用的人应该会有三角大插头必须接…

js获取cookie获取不到问题 vue获取cookie以及获取不到问题

1.下载依赖包 npm i js-cookie -S2.在使用cookie的页面上进行引入 import Cookies from js-cookie3.使用 创建一个在整个网站上有效的CookieCookies.set(name, value);创建一个从现在起7天后过期的cookie&#xff0c;在整个站点上有效&#xff1a;Cookies.set(name, value, …

smarty二维foreach示例[顺代一维数组],再次加强版

2019独角兽企业重金招聘Python工程师标准>>> smarty二维foreach示例[顺代一维数组],再次加强版 WEB2.0 root 2009-4-9 10:46 评论(0) 阅读(682) 大 | 中 | 小 WEB2.0 | 评论(0) | 引用(0) | 阅读(682) view plain print ? {foreach itemrec from$result…

linux 函数学习--kzalloc()

使用include <linux/slab.h>void *kmalloc(size_t size, int flags);static inline void *kzalloc(size_t size, gfp_t flags) { return kmalloc(size, flags | __GFP_ZERO); } 123456说明给 kmalloc 的第一个参数是要分配的块的大小. 第 2 个参数, 分配标志 用kza…

动态链接库和静态链接库

From: http://blog.163.com/zhangjie_0303/blog/static/99082706201081105654484/ 动态链接库dll&#xff0c;静态链接库lib, 导入库lib 目前以lib后缀的库有两种&#xff0c;一种为静态链接库(Static Libary&#xff0c;以下简称“静态库”)&#xff0c;另一种为动态连接库(…

div与div区别小结

两者之间的区别:例如div span得到的是div下所有的span元素&#xff0c;而div>span则是取得的div下第一级的span元素。 示例代码如下&#xff1a; <!DOCTYPE html><html lang"en" xmlns"http://www.w3.org/1999/xhtml"> <head><met…

url的特殊字符编码 encodeURI编码

参考&#xff1a; 编码解码 前沿&#xff1a; 例如上传资源视频图片&#xff0c;针对一些特殊的字符&#xff01;#&#xffe5;%……&*&#xff08;&#xff09;&#xff1f;《{[,./’~ 不做转码的时候url识别会错&#xff0c;图片就不会显示出来&#xff0c;这时候就需要对…

Linux设备驱动之Kobject、Kset

LDD3中说&#xff0c;Kobject的作用为&#xff1a;1、sysfs 表述&#xff1a;在 sysfs 中出现的每个对象都对应一个 kobject, 它和内核交互来创建它的可见表述。2、热插拔事件处理 &#xff1a;kobject 子系统将产生的热插拔事件通知用户空间。 3、数据结构关联&#xff1a;…

40个新鲜出炉的 jQuery 插件和免费教程【上篇】 转载自:梦想天空

40个新鲜出炉的 jQuery 插件和免费教程【上篇】 转载于:https://www.cnblogs.com/chenjunLovefan/archive/2012/07/23/2605003.html

vector, list, map在遍历时删除符合条件的元素

直接看源码&#xff0c;内有详细解释 /*测试vector, list, map遍历时删除符合条件的元素本代码测试环境: ubuntu12 win7_x64*/#include <iostream>#include <vector>#include <list>#include <map>#include <iterator>using namespace std;void…

图片不显示问题 图片url监测改变问题

问题&#xff1a;点击按钮换一换的时候&#xff0c;后台返回的三张小图片的地址还是原来的地址&#xff0c;但是三张小图确实是变了&#xff1b;这时候如果一开始头图是图3&#xff0c;点击换一换后&#xff0c;三张小图变了&#xff0c;此时还是想选择图3为头图&#xff1b;却…

linux设备:cdev和kobj_map

先看kobj_map相关的代码涉及到的文件<linux/kobj_map.h><drivers/base/map.c>[objc] view plaincopyprint?typedef struct kobject *kobj_probe_t(dev_t, intint *, voidvoid *); struct kobj_map; int kobj_map(struct kobj_map *, dev_t, unsigned long, stru…

限定虚拟机可用的CPU利用率

Windows Server 2012姗姗来迟&#xff0c;最新的Hyper-V 3给我们带来更多的惊喜&#xff0c;后续三篇博文和大家共同学习虚拟机CPU竞争机制。 第一部分&#xff1a;分配给虚拟机的CPU资源 第二部分&#xff1a;限定虚拟机可用的CPU利用率 第三部分&#xff1a;争夺CPU资源优先级…

Windows 7 文件夹共享

今天搞了下windows 7下的文件共享&#xff0c;总是搞不定&#xff0c;虽然以前也偶尔有成功过&#xff0c;但未作记录&#xff0c;现在要搞一时搞不定&#xff0c;所以决定好好记录一下。 win7的文件夹共享搞得实在是太麻烦了(对于一般用户而言)&#xff0c;为了权限控制&#…

MYSQL学习笔记 (二)对数据库结构的增删改查

显示数据库 show databases; 选择数据库 use database;//其实database为数据库的名字 创建表 create table tbclass( id int not null auto_increment primary key, className varchar(20) not null unique, studentNum smallint not null )enginemyisam default charsetutf8 插…

将二进制文件bold转化为文件file

参考&#xff1a;bold和file互相转换 let files new window.File([this.blob], file.name, {type: file.type}) File()构造函数的前两个参数为必传

1.the linux device model--kobject kset学习笔记

http://blog.chinaunix.net/uid-22547469-id-4590385.html?utm_sourcejiancool Linux设备模型就是一栋规模宏大的建筑&#xff0c;为了构建它&#xff0c;需要基本的建筑材料钢筋&#xff1a;kobject、若干钢筋组成的钢架结构&#xff1a;kset&#xff0c;还需要一种机制sysfs…

带格式化参数的strcat宏定义

#include <stdio.h>#include <iostream>#include <string.h>using namespace std;// 带格式化参数的strcat宏定义#define Strcat(x, fmt, ...) sprintf(x, "%s" #fmt, x, __VA_ARGS__)int main(void){char buf[200];for(int k 0; k < 4; k){me…