出了点小情况,本来博主画饼说上周可以结束的,但是最近一堆事情要做,不得不拖更了。
承接上文用session来实现用户的登录登出,接下来说说jwt是如何实现这一功能的。
一、jwt概述
1、json:JavaScript对象表示法:用js的对象来表示数据格式,例如[{name:""},{name:""}]
2、token:加密的字符串(标识),客户端带着token向服务器发送请求,以证明自己的身份
二、生成token
看了jwt概述,我们首先要生成token,那么如何生成token,这里我们需要安装一个插件
1、安装egg-jwt插件:npm install --save egg-jwt
2、在plugin.js中引入插件
jwt:{
enable:true,
package:'egg-jwt'
}
3、配置config.default.js文件,设置secret,注意:secret不能泄露
config.jwt = {secret:"yiershizhimao"}
三、用jwt实现功能
- 在controller文件夹下创建jwt.js文件
const Controller = require("egg").Controller
class JwtController extends Controller {
async index() {
this.ctx.body = 'hello jwt'
}
}
module.exports = JwtController
- 在router.js加上跳转的路由
router.get('/jwt', controller.jwt.index)
- 修改jwt.js文件夹获取token,传递的参数一个是需要加密的参数,一个是之前的秘钥,然后就会得到一个加密后完整的token
const Controller = require("egg").Controller
class JwtController extends Controller {
async index() {
let user = {
username: 'xiaoming'
}
//egg-jwt 加密
let token = this.app.jwt.sign(user, this.app.config.jwt.secret)
this.ctx.body = token
}
}
module.exports = JwtController
三、验证流程
1、根据用户信息,生成token,并响应给客户端
2、客户端存储在localStorage中
3、客户端每次请求数据,请求头携带token
4、服务器接收请求是,验证请求头的token,验证成功则响应数据
在上面,我们已经进行了获取token的操作,现在我们需要通过服务器去校验token,我们可以使用下面的这个方法
this.app.jwt.verify(token, this.app.config.jwt.secret) //两个参数,一个token,一个秘钥
我们可以看一下效果:
let decode = this.app.jwt.verify(token, this.app.config.jwt.secret)
this.ctx.body = decode
那么图中的xiaoming就是我们传入的值,iat是时间戳,就是这个token签发的时间。
如果我们将token修改,输入其余的值,那么服务器解析不了,就一定会报错
this.app.jwt.verify('123456', this.app.config.jwt.secret)
但是真正开发的时候,我们肯定不是不能说给客户一个500的页面的,所以需要给一个提示。
try {
let decode = this.app.jwt.verify('123456', this.app.config.jwt.secret)
this.ctx.body = decode
} catch (e) {
this.ctx.body = 'token未能通过验证'
}
那么丐版本的登录验证过程我们就写完了,下面我会放上完整的代码,还不熟悉的小伙伴可以再写一遍熟悉一下,那么接下来,我们就用vue和egg一起来实现用户登录的这一系列过程。
//jwt.js
const Controller = require("egg").Controller
class JwtController extends Controller {
async index() {
let user = {
username: 'xiaoming'
}
//egg-jwt 加密
//用户登录
let token = this.app.jwt.sign(user, this.app.config.jwt.secret)
try {
let decode = this.app.jwt.verify(token, this.app.config.jwt.secret)
this.ctx.body = decode
} catch (e) {
this.ctx.body = 'token未能通过验证'
}
}
}
module.exports = JwtController
四、vue和egg实现用户登录
1、首先要搭建一个vue的初始项目,这个我知道大家都会,然后我们需要两个页面,一个home.vue,一个login.vue。(这里呢,路由,axios,element ui都是要准备好的,都要用)ps:提醒一下,报路由的错,就降版本
首页
登陆页
//index.js
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const routes = [{
path: '/',
redirect: '/login'
},
//登陆页面
{
path: '/login',
name: 'Login',
component: () => import('@/views/login.vue'),
},
//首页页面
{
path: '/home',
name: 'Home',
component: () => import('@/views/home.vue'),
},
//学生管理页面
{
path: '/student',
name: 'Student',
component: () => import('@/views/student.vue'),
}
]
var router = new VueRouter({
routes,
mode: "history"
})
export default router;
解析:这里我就主要放这三个了,其余的,app.vue里面该怎么写,main.js怎么写,这个大家都自行去研究了,为了方便大家找问题,我会在这个栏目的最后一章的结尾放上,git的地址,大家如果有需要可以去上面拿资料
2、开始丰富登录页,我看到挺多刚毕业的小伙伴去面试,都会让他们去做一个简单的登录页面,所以说,这里为了方便,我们就直接用element ui了。我们目前只需要做一个点击登录按钮,跳转到首页,不需要其他的操作,就纯跳转。
ps:这里,预处理器,我们不用scss,用stylus。记得去安装一下。
npm install stylus --save
npm install stylus-loader --save
我这里是自己画的一个比较简单的页面,大家自行参考就行了(login.vue):
登录系统
登 录
成品图:
解析:先提醒一下,如果安装了stylus使用报错了,不要慌,将
"stylus": "^0.54.7","stylus-loader": "^3.0.2"
这两个放在devDependencies里面,然后重新安装依赖再次运行就可以了。
写这个页面的逻辑就是,整体的盒子对于页面居中对齐,然后标题以及按钮对于盒子居中对齐,点击按钮事件,实现路由的基础跳转到首页。
3、接下来写后台登录的功能
- 首先要先去写路由的跳转信息,一个是登录的接口,一个是检测token有没有的接口
router.post('/jwtlogin', controller.jwt.doLogin)
router.get('/jwtmessage', controller.jwt.getMessage)
-其次去jwt.js里面写上对应的方法:
一、doLogin方法是用来收取前端传来的用户和用户密码,这里会通过之前讲过的sign方法,给前端返回一个token
async doLogin() {
let user = this.ctx.request.body.user
if (user.name === 'xiaoming' && user.password === '123') {
let user_jwt = {
name: user.name
}
let token = this.app.jwt.sign(user_jwt, this.app.config.jwt.secret)
this.ctx.body = {
code: '200',
token: token
}
} else {
this.ctx.body = {
code: '400',
msg: '用户名或密码错误'
}
}
}
二、getMessage方法是用来检测token有没有,如果token没有问题,则返回数据。(这里暂时先不写,等下面再写这一块的方法)
- 回到我们的home.vue页面,我们需要通过调接口去验证后台代码写的有没有问题
登录系统
登 录
解析:引用axios,调登录的接口,传入用户名和密码,当返回的code是200的时候,则用localStorage去存储token,并且跳转到首页,如果不对,就报接口返回的错误。
- 首页home.vue需要我们加上一个按钮去验证token,一般来讲,实际的开发中,我们调接口,为了安全都会将token放入请求的接口上面
home.vue:
请求数据
jwt.js:
//验证token
async getMessage() {
this.ctx.body = 'hello world'
}
- 此时上面的步骤,只是测试点击请求数据按钮,打印接口返回数据,并没有验证token,所以接下来我们需要这样做:我们需要从localStorage拿到存储的token,并将token放入请求头上
(友情提醒:关于headers加在哪里,如果你是get请求,就写在,URL后面,如果你是get请求,url+传入的参数+headers)
请求数据
- 只是单纯的加上了token的请求头还不够,还需要后台接口的验证,之前我们上面已经写过了如何去判断token的有没有用,所以我们直接拿过来即可
//验证token
async getMessage() {
let token = this.ctx.request.header.token
try {
let decode = this.app.jwt.verify(token, this.app.config.jwt.secret)
this.ctx.body = decode
} catch (e) {
this.ctx.body = 'token未能通过验证'
}
}
- 写到这里,我们是没办法去测试,没有token的情况的,所以,我们需要在页面上加上一个注销按钮:
请求数据
注销
此时我们点击注销按钮,会将localStorage里面存储的token置空,其实你removeItem也行,那么,我们就会收到后台告知我们的错误,token不存在。
- 按照正常的逻辑,当接口报token未通过验证的时候,我们就应该返回登录页,让客户重新登录获取token,所以这里一般我们有两种写法,一种就是路由守卫,一种就是你直接注销,清空token回到登录页面,但是真正开发中,我们的token不是永远有效的,他会有时间,所以我们一般还是会选择去写路由守卫。
在router.js里面加上
//路由守卫
router.beforeEach((to, from, next) => {
if (to.path === '/login') {
next()
} else {
if (localStorage.getItem("token")) {
next()
} else {
next("/login")
}
}
})
那么到这里位置,用户的登录状态就全部讲完了,非常感谢大家的观看,最近博主遇到了一个为了工作和爱情而烦恼的小朋友,我们打游戏都是奔着赢去的,当然了,有人会说,赢不赢无所谓的,每个人的态度不一样,想法就会不同,而博主觉得,玩游戏不一定为了赢,只是我不想输,这句话是来自rng的lol选手ad gala说的话,我觉得和人生也一样,尽力去赢,我们都不想输,最后给大家带来了新的推荐歌曲,来自我嵩哥的《温泉》。
传送门:
1、第一章 Egg框架概述:https://www.jianshu.com/p/bfdaecb5a18c
2、第二章 路由与控制器:https://www.jianshu.com/p/62edeb088d76
3、第三章 插件:https://www.jianshu.com/p/e8d39f446f46
4、第四章 用户登录状态(上) :https://www.jianshu.com/p/a43759eab484