/注:校驗token,獲取headers⾥里里的Authorization的token方法,要寫在路由加載之前,靜態資源之后
app.use(expressJWT({
secret: PRIVATE_KEY
}).unless({
path: ['/api/user/register','/api/user/login'] //⽩白名單,除了了這⾥里里寫的地址,其他的URL都需要驗證
}));
一、生成token
1、安裝jsonwebtoken
npm install jsonwebtoken -S
2、在公共文件中定義一個秘鑰和過期時間(單位是秒)
module.exports = {
"PRIVITE_KEY":"我是秘鑰",
"EXPIRESD":60*60*24
}
3、在需要生成token的頁面引入jsonwebtoken(路由頁面)
// jwt生成token
var {PRIVITE_KEY,EXPIRESD} = require("../utils/store")
const jwt = require("jsonwebtoken");
//jwt.sign()方法可生成token,第一個參數寫的用戶信息進去(可以寫其他的),第二個是秘鑰,第三個是過期時間
let token = jwt.sign({username},PRIVITE_KEY,{expiresIn:EXPIRESD});
二、校驗和解密token(此方法寫在靜態資源加載之后,不然靜態資源不能訪問))
1、安裝express-jw
npm install express-jwt
2、校驗token,獲取headers⾥里里的Authorization的token
前端token值格式 Bearer+token 這是express-jwt規定的前端格式
在入口文件app.js中引入express-jw以及token加密時使用的秘鑰
const expressJWT = require('express-jwt');
var { PRIVITE_KEY } = require("./utils/store");
//使用此方法攔截所有請求看token是否正確(此方法寫在靜態資源加載之后,不然靜態資源不能訪問)
app.use(expressJWT({
secret: PRIVATE_KEY
}).unless({
path: ['/api/user/register','/api/user/login'] //⽩白名單,除了了這⾥里里寫的地址,其他的URL都需要驗證
}));
在app.js中的錯誤中間件定義token的處理
// error handler
app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError') {
// 這個需要根據⾃自⼰己的業務邏輯來處理理
res.status(401).send({code:-1,msg:'token驗證失敗'});
}else {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
}
});
在路由接口中可以使用req.user拿到token解密的值
路由頁面如下
var express = require('express');
var router = express.Router();
var querySql = require("../db/index");
// md5加密key和方法
var {key} = require('../utils/store');
var {md5} = require("../utils/index")
// jwt生成token
var {PRIVITE_KEY,EXPIRESD} = require("../utils/store")
const jwt = require("jsonwebtoken");
// 登錄接口
router.post("/login",async (req,res,next) => {
try {
// 對應前台的傳參
let {username,password} = req.body;
// 跟數據庫對應,看是否存在當前用戶
password = md5(`${password}${key}`);
let result = await querySql("select * from user where username = ? and password = ?",[username,password]);
if(result && result.length != 0){
// 數據庫有當前用戶時返回token
let token = jwt.sign({username},PRIVITE_KEY,{expiresIn:EXPIRESD});
res.send({
code:0,
msg:"登錄成功",
token:token
})
}else {
res.send({
code:-1,
msg:"用戶名或者密碼錯誤"
})
}
} catch (error) {
// p拋出異常並交由錯誤中間件處理
console.log(error);
next(error);
}
})
// 注冊接口
router.post('/register', async (req, res, next)=>{
let {
username,
password,
nickname
} = req.body;
try {
// 查詢當前用戶名在不在數據庫中(使用async方法后必須使用await方法才有值返回,不然返回promise對象)
let user = await querySql("select * from user where username = ?", [username]);
// 存在res即是數據庫中有數據
if (user && user.length != 0) {
res.send({
code: -1,
msg: "用戶已注冊"
})
} else {
// 對密碼進行加密
password = md5(`${password}${key}`);
// async 和 await 向數據庫插入數據
await querySql("insert into user(username,password,nickname) values (?,?,?)", [username, password, nickname]);
res.send({
code: 0,
msg: "注冊成功"
})
}
} catch (error) {
console.log(error)
next(error)
}
});
// 查詢用戶信息接口
router.get("/info",async (req,res,next)=>{
// 通過username獲取用戶信息
console.log(req.user)
let {username} = req.body;
try {
let userInfo = await querySql("select * from user where username = ?",[username]);
res.send({
code:0,
userInfo:userInfo
})
} catch (error) {
console.log(error);
next(error);
}
})
module.exports = router;
app.js寫法如下
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var cors = require("cors");
// 使用express-jwt來進行token的解密和驗證
const expressJWT = require('express-jwt');
var { PRIVITE_KEY } = require("./utils/store");
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users')
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// 處理跨域
app.use(cors())
// 日志
app.use(logger('dev'));
// 使用post請求
app.use(express.json());
app.use(express.urlencoded({
extended: false
}));
// 使用cookie
app.use(cookieParser());
// 訪問靜態資源目錄
app.use(express.static(path.join(__dirname, 'public')));
// 校驗token,獲取headers⾥里里的Authorization的token,要寫在路由加載之前,靜態資源之后
app.use(expressJWT({
secret: PRIVITE_KEY
}).unless({
path: ['/api/user/register', '/api/user/login'] //⽩白名單,除了了這⾥里里寫的地址,其他的URL都需要驗證
}));
// 使用路由
app.use('/', indexRouter);
app.use('/api/user', usersRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError') {
// 這個需要根據⾃自⼰己的業務邏輯來處理理
res.status(401).send({code:-1,msg:'token驗證失敗'});
}else {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
}
});
module.exports = app;