一、jsonwebtoken 用于生成token(加密)
> jsonwebtoken
1. 安装
npm i jsonwebtoken --save
2. 使用
2.1 引入
2.2 加密
用户登录成功后,后端生成token,返回给前端
二、passport、passport-jwt 用于验证token(解密)
passport-jwt和passport中间件来验证token
passport-jwt是一个针对jsonwebtoken的插件,passport是express框架的一个针对密码的中间件
passport-jwt
-
安装:
npm i passport-jwt passport --save
-
在server.js 入口文件中,引入passport
-
初始化passport,并引入passport.js文件
-
在passport.js文件中,具体配置passport
const JwtStrategy = require('passport-jwt').Strategy,ExtractJwt = require('passport-jwt').ExtractJwt;
// const mongoose = require("mongoose");
const {User} = require('../models/User.js')
// 引入keys, 拿到secret
const keys = require('../config/db.js')
const opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = keys.secretOrKey;module.exports = (passport) => {passport.use(new JwtStrategy(opts, function(jwt_payload, done) {console.log(jwt_payload)}));
}
1)请求/current时,请求体带上token的情况:
2)请求/current时,请求头没有带上token的情况:
在users表中,添加一个字段用于权限认证,
然后接口代码users.js做如下修改:
- 注册时,填写identify身份字段,注册成功后返回用户的基本信息:
- 用户输入正确的email和password成功登录之后,给前端返回token
- 前端请求需要登录之后才能访问的接口时,需要在请求头中加上token,携带上token信息,否则无法拿到接口返回的数据。
// 登录 注册模块
const express = require("express")
const router = express.Router()
const bcrypt = require("bcrypt")
const gravatar = require('gravatar')
const jwt = require('jsonwebtoken')
const keys = require('../../config/db.js')const passport = require('passport')const User = require('../../models/User')router.get("/test", (req, res) => {res.json({ msg: "login works" })
})// 注册接口
router.post("/register", (req, res) => {console.log(req.body)// 查询数据库中是否存在该email的用户User.findOne({email: req.body.email}).then((user) => {if (user) {return res.status(400).json({ msg: "邮箱已被注册" })} else {var avatar = gravatar.url(req.body.email, {s: '200', r: 'pg', d: 'mm'});const newUser = new User({name: req.body.name,email: req.body.email,avatar: avatar,password: req.body.password,identify: req.body.identify})// 对密码进行加密bcrypt.genSalt(10, function (err, salt) {bcrypt.hash(newUser.password, salt, function (err, hash) {if (err) throw err;newUser.password = hashnewUser.save().then((user) => {res.json(user)}).catch((err) => {console.log(err)})});});}})
})// 登录接口, 返回token jwt passport
router.post("/login", (req, res) => {const email = req.body.emailconst password = req.body.password// 根据email查询,数据库中是否存在该用户User.findOne({email: email}).then((user) => {if (!user) {return res.status(404).json({msg: '用户不存在!'})}// 用户存在,则检查密码是否一致bcrypt.compare(password, user.password).then((isMatch) => {if (isMatch) {const rule = {id: user.id, name: user.name,avatar: user.avatar,identify: user.identify}jwt.sign(rule, keys.secretOrKey, {expiresIn: 3600}, (err, token) => {if (err) throw err;return res.json({success: true,token: "Bearer " + token})})} else {return res.status(400).json({msg: '密码错误!'})}})})})// 登录后才能访问的接口
router.get("/current", passport.authenticate('jwt', {session: false}), (req, res) => {const {_id ,name, email, avatar, identify, date} = req.userres.json({id: _id,name: name,email: email,avatar: avatar,identify: identify,date: date})
})module.exports = router