Vue项目中实现用户登录及token验证
一、什么是token
token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。
简单token的组成;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token的前几位以哈希算法压缩成的一定长度的十六进制字符串。为防止token泄露)。
二、token的作用
1、防止表单重复提交:主要的理念是,客户端初始化的时候(一般就是刚刚进入页面的时候)就调用后端代码,后端代码生成一个token,返回给客户端,客户端储存token(可以在前台使用Form表单中使用隐藏域来存储这个Token,也可以使用cookie),然后就将request(请求)中的token与(session)中的token进行比较
2、用来作身份验证:
(1)身份认证概述
由于HTTP是一种没有状态的协议,它并不知道是谁访问了我们的应用。这里把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下次这个客户端再发送请求时候,还得再验证一下。
通用的解决方法是:当用户请求登录的时候,如果没有问题,在服务端生成一条记录,在这个记录里可以说明登录的用户是谁,然后把这条记录的id发送给客户端,客户端收到以后把这个id存储在cookie里,下次该用户再次向服务端发送请求的时候,可以带上这个cookie,这样服务端会验证一下cookie里的信息,看能不能在服务端这里找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。
以上所描述的过程就是利用session,那个id值就是sessionid。我们需要在服务端存储为用户生成的session,这些session会存储在内存,磁盘,或者数据库。
(2)基于token机制的身份认证:使用token机制的身份验证方法,在服务器端不需要存储用户的登录记录。流程如下:
- 客户端使用用户名和密码请求登录。
- 服务端收到请求,验证用户名和密码。
- 验证成功后,服务端会生成一个token,然后把这个token发送给客户端。
- 客户端收到token后把它存储起来,可以放在cookie或者Local Storage(本地存储)里。
- 客户端每次向服务端发送请求的时候都需要带上服务端发给的token。
- 服务端收到请求,然后去验证客户端请求里面带着token,如果验证成功,就向客户端返回请求的数据。
(3)JWT机制优缺点
优点:
- 支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.
- 无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.
- 更适用CDN: 可以通过内容分发网络请求你服务端的所有资料(如:javascript,HTML,图片等),而你的服务端只要提供API即可.
- 去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可.
- 更适用于移动应用: 当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。
- CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。
- 性能: 一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算 的Token验证和解析要费时得多.
- 基于标准化:你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在多个后端库(.NET, Ruby, Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft)
缺点:
- JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
- 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。
- JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令×××的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
三、Vue项目中实现用户登录及token验证
1、思路如下:
- 第一次登录的时候,前端调后端的登陆接口,发送用户名和密码
- 后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token
- 前端拿到token,将token存储到localStorage和vuex中,并跳转路由页面
- 前端每次跳转路由,就判断 localStroage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面
- 每次调后端接口,都要在请求头中加token
- 后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401
- 如果前端拿到状态码为401,就清除token信息并跳转到登录页面
2、后台接口(node.js)的实现
(1)安装JWT: npm install jsonwebtoken --save
JWT(Json Web Token)是一种身份验证及授权方案,简单的说就是客户端调用 api 时,附带上一个由 api 端颁发的 token,以此来验证调用者的授权信息。
(2)JWT的常用函数:
A、sign(payload, secretOrPrivateKey, [options, callback])
B、verify(token, secretOrPublicKey, [options, callback])
C、decode(token [, options])
(3)后台代码实现:
var express = require('express');
var router = express.Router();
var pool = require('../config/blogdb.js')
const jwt = require('jsonwebtoken'); //引入jwt模块/*** http://localhost:8089/blog/login*/
router.post('/login',function(req,res){let username = req.body.username;let password = req.body.password;console.log("用户名="+username)pool.getConnection(function(err,conn){if(err){console.log('连接数据库失败!')}else{let data=[username,password]let sql = "select * from admin where username= ? and password = ?";conn.query(sql,data,function(error,results){if(error){console.log(error)}if(results != null){ //若查询结果不为空const payload = { //定义token的有限载荷name: results.username}const secret = 'deyun' //给定密钥//定义tokenconst token = jwt.sign(payload,secret,{ 'expiresIn':1440});// 设置过期时间res.json({ //将响应信息转换为json格式success: true,message: 'Enjoy your token',token: token})}conn.release(); //释放数据库连接对象})}});})module.exports = router;
三、前端Vue实现
1、创建项目:vuetokendemo,目录结构如下
2、给项目安装vuex模块
3、main.js文件
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios' import store from './store' //导入store
Vue.config.productionTip = false
Vue.prototype.$http = axios
// 导航守卫
// 使用 router.beforeEach 注册一个全局前置守卫,判断用户是否登陆
router.beforeEach((to,from,next) => {if(to.path === '/login'){next();}else{let token = window.localStorage.token;if(token === 'null' || token === '' || token === undefined){next('/login')}else{next();}}
});
//添加请求拦截器
axios.interceptors.request.use(config => {if(store.state.token){config.headers.common['token'] = store.state.token.token}return config;},error => {//请求错误return Promise.reject(error);}
);
//添加响应拦截器
axios.interceptors.response.use(response => {return response;},error => {if(error.response){switch(error.response.status){case 401:localStorage.removeItem('token');router.replace({path: '/login',query: {redirect: router.currentRoute.fullPath //登录成功后跳入浏览的当前页}})}}}
)
new Vue({el: '#app',router,store,components: { App },template: '<App/>'
})
4、login.vue组件
<template><div><input type="text" v-model="loginForm.username" placeholder="用户名"/><input type="text" v-model="loginForm.password" placeholder="密码"/><button @click="login">登录</button></div>
</template><script>
import { mapMutations } from 'vuex'
export default {data () {return {loginForm: {username: '',password: ''}};},methods: {...mapMutations(['$_setStorage']),login () {let _this = this;if(this.loginForm.username === '' || this.loginForm.password === ''){alert('账号或密码不能为空');}else{this.$http({method: 'post',url: 'http://localhost:8089/blog/login',data: _this.loginForm}).then(res=>{console.log(res.data)_this.$_setStorage({Authorization:res.data.token});_this.$router.push('/home');alert('登录成功')}).catch(error=>{alert('账号或密码错误');console.log(error)})}}}
}
</script>
5、home.vue组件
<template><h1>首页,跳转成功</h1>
</template><script>
export default {
}
</script>
<style>
</style>
6、store/index.js文件
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)
const key = 'token'
const store = new Vuex.Store({state () {return {token: localStorage.getItem('token')?localStorage.getItem('token'):''}},getters: {getSortage: function(state) {if(!state.token){state.token =JSON.parse(localStorage.getItem(key))}return state.token}},mutations: {$_setStorage(state,value){state.token = valuelocalStorage.setItem(key,JSON.stringify(value))},$_removeStorage(state){state.token = null;localStorage.removeItem(key)}}
})
export default store;
7、router/index.js文件
import Vue from 'vue'
import Router from 'vue-router'
import login from '@/components/login'
import home from '@/components/home'
Vue.use(Router)const router = new Router({routes: [{path: '/', redirect: '/login'},{path: '/login',name: 'login',component: login},{path: '/home',name: 'home',component: home}]
});
//导航守卫
//使用router.beforeEach注册一个全局前置守卫,判断用户是否登录
router.beforeEach((to,from,next)=>{if(to.path === '/login'){next();}else{let token = localStorage.getItem('Authorization');if( token === 'null' || token === ''){next('/login')}else{next();}}
});
export default router;
8、运行效果
Vue项目中实现用户登录及token验证相关推荐
- vue项目中实现用户登录以及token验证
文章目录 前言 一.总体逻辑图 二.各环节涉及知识点以及代码 1.jwt(这里只说用法,至于为什么用它,详细可查官网) 2.返回token并存入vuex做持久化 3.路由守卫 4.axios请求拦截 ...
- vue 用户名重复验证_Vue项目中实现用户登录及token验证
在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下: 1.第一次登录的时候,前端调后端的登陆接口,发送用户名和密码 2.后端收到请求,验证用户名和密码,验证成功,就给前端返回一个to ...
- wegame每次登陆都要滑动验证_Vue项目中实现用户登录及token验证
在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下: 1.第一次登录的时候,前端调后端的登陆接口,发送用户名和密码 2.后端收到请求,验证用户名和密码,验证成功,就给前端返回一个to ...
- java token_Java用户登录之token验证
1.场景还原 可能还有很多小伙伴对token概念朦朦胧胧,今天笔者以项目中的用户登录的token验证需求跟大家讲讲其中的来龙去脉,希望能够理清大伙的思路. 2.需求分析 这个需求可能早已是老生常谈,但 ...
- vue项目中的回车登录
vue项目中的回车登录:(搭配element ui 的使用 如果是原生,@keyup.enter="login(form)"就可以了) 在密码框上加代码:v-model=" ...
- Vue实现用户登录及token验证
写博客不是为了博眼球 而是为了记笔记 请勿复制全部代码防止错乱,这里放源码是为了个人做笔记 //登录 login: params => { return API.POS ...
- 用户登录,token验证开发(含过期时间)
其实所谓的token,就是一串加密的字符串 需求:用户登录访问页面后,在未退出登录账号的情况下,再次访问页面无需再次登录 首先我们抛开过期时间不管 设计思路:主要是前端有个缓存可以存取一些信息一段时间 ...
- Vue项目中如何实现用户登录及token验证?
思路: 1.第一次登录的时候,前端调后端的登陆接口,发送用户名和密码 2.后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token 3.前端拿到token,将token存储到localSt ...
- 记一次项目中所有用户登录不成功的解决过程
周日晚上10点钟,公司监控部来电,我负责的A系统全部登录失败,失败提示:由于你循环登录,为了保证B系统的安全,已锁定你的用户名.这意味着晚上加班的那些客服们无法工作了,事情很严重.怎么办,解决吧. 介 ...
最新文章
- springboot RestTemplate httpclient
- 目前流行的源程序版本管理软件有什么优缺点?
- c++对象拷贝语意学
- Problem - 3936 FIB Query
- Spring Security 3.1 自定义 authentication provider
- 微信红包接口 java_【java微信开发】红包接口调用
- MiniDao持久层 Vs Mybatis
- 合成孔径成像算法与实现_MIMO OFDM宽幅SAR成像仿真与图像融合技术
- linux中vim查看最后五行命令,Linux系统中Vi常用命令及高级应用
- fckeditor异常总结---WARN No appenders could be found for logger的解决方法
- 基于cxf框架javaweb服务说明
- pytorch 语义分割loss_关于pytorch语义分割二分类问题的两种做法
- 获取全年所有节假日非工作日
- html仿excel冻结 css,css实例:实现gridview仿excel冻结列
- 昔者,圣人之作易也,幽赞神明而生蓍
- 天才小毒妃 第917章 深藏不露大财主
- 创奇文书档案管理软件 V8.1
- 刚毕业不久就被裁了,然后就一直没上班了,谈谈体验吧!
- 关于WinForm中Pannel的定位问题 May 18th, 2010
- ArchieOpenGL教程扩展一:修改背景色颜色