token流程;
session VS token:
详细session:开始一个koa2 -(4)-session
那么开始
本文前后端完全分离。前端通过ajax请求后端数据;不再使用模板引擎;
假设你已经用vue-cli3 制作了一个前端项目E:\myKun\yuntumap-web;这个项目的后台语言可以是php、java、.net、还有c#等等;
在原有的前端项目中我们来尝试写一个koa2语言的后台与之匹配;
上图;
而后端koa2的目录;结合前几节课的知识点;
好现在开始。
1运行你的前端项目;运行后浏览器自动打开 http://localhost:8080
2运行后台koa2-test ;因为都在本地运行的;所以 确保后端和前端的端口不一致;比如3000;
3安装 koa-cors 他可以解决跨域问题;
npm install koa-cors --save
在app.js 中
// CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
// 下面以koa2-cors为例,
const cors = require('koa-cors');
// 具体参数我们在后面进行解释
app.use(cors({
origin: function (ctx) {
if (ctx.url === '/test') {
return "*"; // 允许来自所有域名请求
}
return 'http://localhost:8080'; // 这样就能只允许 http://localhost:8080 这个域名的请求了
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
maxAge: 5,
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}))
这里插个题外话,koa2每次修改代码都重启一次太麻烦;我们安装nodemon ,热启动;
npm install --save-dev nodemon
在package.json 中修改
"scripts": {
"start": "nodemon ./bin/www"
},
现在我们回到前端;
将请求的根路径改成
let rootUrl = 'http://localhost:3000'
ajax每次请求;
这个ajax我自己按照喜好封装起来了。具体vue插件/公共方法属性
所以登录的ajax使用;
login(){
let data = {
account: this.account,
password: md5(this.password),
};
this.myAjax('/api/AlarmHandle/GetLogin', data).then(res=>{
this.toast(res.ReturnMsg);
this.config.setItem('token', res.Token)
this.config.setItem('account',this.account);
this.mytime= setTimeout(()=>{
this.goHome();
},1000)
})
}
好,回到后端;
1安装token相关中间件
jsonwebtoken,服务认证生成一个json对象;
koa-jwt 主要提供路由权限控制的功能,它会对需要限制的资源请求进行检查;
在app.js中
const koajwt = require('koa-jwt');
//通过 app.use 来调用该中间件,并传入密钥 {secret: 'my_token'},unless 可以指定哪些 URL 不需要进行 token 验证。
app.use(koajwt({
secret: config.secret
}).unless({
path: [/\api\/AlarmHandle\/GetLogin/]
}));
新建目录token/createToken.js
/**
* Created by Administrator on 2018/12/4 0004.
*/
const jwt = require('jsonwebtoken');
const config=require('../config')
module.exports = function(name){
//生成token
//第一个参数是载荷,用于编码后存储在 token 中的数据
//第二个是密钥,自己定义的,验证的时候也是要相同的密钥才能解码
//第三个是options,可以设置 token 的过期时间
const token = jwt.sign({name: name}, config.secret, {expiresIn: '10s'});
console.log(token)
return token;
};
新建目录token/checkToken.js
const jwt = require('jsonwebtoken');
const util = require('util')
const verify = util.promisify(jwt.verify) // 解密
const config=require('../config')
//检查token是否过期
module.exports = async (token) =>{
if (token) {
let payload
try{
payload = await verify(token, config.secret) // // 解密,获取payload
console.log(payload,"payload")
}catch (err){
return false
}
return true
} else {
return false;
}
};
在 myrouter/login.js
const router = require('koa-router')();
const sql = require('../async-db/sql.js')
let createToken = require('../token/createToken.js')
let checkToken = require('../token/checkToken.js')
router.get('/api/AlarmHandle/GetLogin', async (ctx, next) => {
let name = ctx.query.account;
let pass = ctx.query.password;
await sql.findUserData(name)
.then(res=> {
if (res.length != 0) {
if (pass === res[0]['pass']) {
console.log('登录成功')
ctx.response.body = {
ReturnCode: "SUCCESS",
ReturnMsg: '登录成功',
Token: createToken(name)
}
} else {
ctx.response.body = {
ReturnCode: "FAIL",
ReturnMsg: '密码错误',
}
}
} else {
ctx.response.body = {
ReturnCode: "FAIL",
ReturnMsg: '账号不存在',
}
console.log('登录失败')
}
next();
})
})
假设MySQL中已经存在;
登录成功后,前端再次请求服务器,需要把token返回给后台;
所以。在myrouter/login.js中再加入前端请求的新路由/api/AlarmHandle/GetAlarmOrder
router.get('/api/AlarmHandle/GetAlarmOrder', async (ctx, next) => {
let token = ctx.query.Token
let istoken = await checkToken(token);
ctx.response.body = {
ReturnCode: istoken ? "SUCCESS" : 'FAIL',
ReturnMsg: istoken ? '操作成功' : 'token失效',
TokenInvalid: istoken
}
})
前端响应;
用户登出;在本地清空储存的token即可;
loginOut(){
localStorage.clear();
this.$router.push('/login')
}