开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验

token流程;

  • 前端使用用户名、密码来请求服务器
  • 服务器通过数据库查询等操作验证用户的信息
  • 服务器通过验证发送给用户一个token
  • 前端存储token(cookie、sessionStorage、loaclStorage),并在每次请求时附送上这个token值
  • 后台验证token值,并返回数据
  • token会有过期,前端登出的时候直接清空本地token,服务端不需要任何操作

 

session VS  token:

  • session要求服务端存储信息,并且根据id能够检索,而token不需要。在大规模系统中,对每个请求都检索会话信息可能是一个复杂和耗时的过程。但另外一方面服务端要通过token来解析用户身份也需要定义好相应的协议。
  • session一般通过cookie来交互,而token方式更加灵活,可以是cookie,也可以是其他header,也可以放在请求的内容中。不使用cookie可以带来跨域上的便利性。
  • token的生成方式更加多样化,可以由第三方服务来提供

详细session:开始一个koa2 -(4)-session


那么开始

本文前后端完全分离。前端通过ajax请求后端数据;不再使用模板引擎;

假设你已经用vue-cli3 制作了一个前端项目E:\myKun\yuntumap-web;这个项目的后台语言可以是php、java、.net、还有c#等等;

在原有的前端项目中我们来尝试写一个koa2语言的后台与之匹配; 

上图;

开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第1张图片开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第2张图片

开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第3张图片

 开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第4张图片

 而后端koa2的目录;结合前几节课的知识点;

开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第5张图片

 好现在开始。

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每次请求;

开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第6张图片

这个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)
		})
	  }

开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第7张图片

好,回到后端;

 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/]

}));

开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第8张图片

新建目录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中已经存在; 

开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第9张图片

 

登录成功后,前端再次请求服务器,需要把token返回给后台;

开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第10张图片

 所以。在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
  }

})

前端响应;

开始一个koa2-(6)-前后端分离+vue-cli3+JWT生成token登录校验_第11张图片

用户登出;在本地清空储存的token即可;

 loginOut(){
		localStorage.clear();
		this.$router.push('/login')
	  }

 

你可能感兴趣的:(koa2,MySQL,node,vue)