使用jwt生成token
JSON Web Token(JWT)是目前最流行的跨域身份驗證解決方案。
- 1、引入jsonwebtoken
var jwt = require('jsonwebtoken');
- 2、生成一個token
// 生成一個token
const secret = 'yating';
function makeToken(name, password, exp) {
return token = jwt.sign({ name, password, exp }, secret);
}
類似這樣的:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidGluZ2VyIiwicGFzc3dvcmQiOiJndW93ZWkiLCJleHAiOjE1Njc0MTQ1NjEsImlhdCI6MTU2NzQxMjc2MX0.75ARiai6NXo0UrqMyW30eumfAz4zNzqfZT0nm85LlFk
具體的原理什麼的,請請大家自己去網上找一下,我也講的不是很清楚。
- 3、驗證token是否過期,我這裏用了一個promis方法,沒有過期的時候,decoded會返回token的解析結果。
// 驗證token
function verifyToken(token) {
return new Promise((reslove, reject) => {
jwt.verify(token, secret, (err, decoded) => {
if (err) {
// 驗證過期失敗
reject(err);
} else {
// 驗證成功傳用戶信息
reslove(decoded)
}
})
})
}
- 4、再次之前要比對一下存在數據庫裏的用戶是否存在與請求的token一致
// 對比數據庫裏的token
function verifyMysqlToken(token, userName) {
return new Promise((reslove, reject) => {
// 只要token和用戶名爲空,name就失敗
if(token==undefined||userName==undefined){
reject();
}else{
// 1、先在數據庫裏比對token
var sql = `select token from users where user='${userName}'; `
mysqlPool(sql).then(data => {
// 如果請求的token跟存在數據庫裏的token一直,name就驗證是否過期;
var mysqlToken = data[0].token
console.log(mysqlToken == token,"對比結果")
if (mysqlToken == token) {
console.log("請求的token跟數據庫裏的token一致")
// 開始驗證,調用驗證函數,成功後調用reslove的方法,失敗就reject()
verifyToken(token).then(data => reslove(data)).catch(err => reject())
} else {
// 不一致,則結束;
console.log("不一致")
reject()
}
})
}
})
}
- 5、以後涉及用到權限的時候都套用這個方式,其中1、2我已經合在verifyMysqlToken方法裏了。
1、對比一下請求的token是否與數據庫裏的token一致,不一致則結束;
2、一致,則驗證一下token是否過期。過期則結束;
3、token沒有過期,則有權限操作。
//下面跟權限有關的接口都要套上這個格式
var ifok = verifyMysqlToken(req.headers.token, req.headers.username);
ifok.then(data => {
//有權限操作的代碼,對數據庫進行操作
}).catch(err => {
//無權限操作的代碼,不對數據庫操作
});
- 6、當用戶登錄成功時,與數據庫裏的賬號跟密碼進行比對。然後就開始生成token,並且設置一下過期時間,這裏我設置的是3分鐘。返回給前端。
// 登錄
router.post('/login', function (req, res, next) {
var user = req.body.user;
var password = req.body.password;
var sql = `select * from users where user='${user}' and password='${password}'; `
mysqlPool(sql)
.then((data) => {
if (data.length == 1) {
var expTime = Math.floor(Date.now() / 1000) + 60 * 3;//過期時間1分鐘
var token = makeToken(user, password, expTime);//生成token
// 將token存到數據庫裏
var sqlsaveToken = `UPDATE users SET token="${token}"where user='${user}' and password='${password}';`
mysqlPool(sqlsaveToken).then(data => { console.log("更新用戶token") }).catch(err => { console.log("更新失敗") });
// 返回token給前端
var message = {
token:token,
info: "登錄成功~",
code: 1
}
res.send(message);
} else {
var message = {
info: "不存在用戶~",
code: 0
}
res.send(message);
}
})
.catch((err) => {
var message = {
info: "請求錯誤!",
code: -1
}
res.send(message)
})
});
- 7、舉個例子:
// 刪除
router.post('/delete', function (req, res, next) {
var ifok = verifyMysqlToken(req.headers.token, req.headers.username);
// 有權限則可以操作:
ifok.then(data => {
var tableName = req.body.tableName;
var id = req.body.id;
var sql = `DELETE FROM ${tableName} WHERE id=${id};`
mysqlPool(sql)
.then((data) => {
var message = {
info: "刪除成功~",
code: 1
}
res.send(message);
})
.catch((err) => {
var message = {
info: "刪除失敗",
code: 0
}
res.send(message)
})
}).catch(() => {
var message = {
info: "你沒有權限操作o(´^`)o~",
code: -1
}
res.send(message)
});
});
- 8、前端獲得token以後要存在session裏。然後每次請求的時候,把token放在header裏。
function POST(url, params) {
return new Promise((scuessful, fail) => {
var userInfo = sessionStorage.getItem('userInfo');
if(userInfo){
axios.defaults.headers.token = JSON.parse(userInfo).token;
axios.defaults.headers.userName = JSON.parse(userInfo).userName;
}
axios.post(url, params)
.then(function (response) {
scuessful(response);
})
.catch(function (error) {
fail(error);
});
});
}