登录鉴权之Cookie&Session&JWT,nodejs登录鉴权详解、前后端登录鉴权的几种方式、jsonwebtoken是什么

凉菜凉凉 2024-07-24 11:33:01 阅读 72

Cookie&Session

「HTTP 无状态」我们知道,HTTP 是无状态的。也就是说,HTTP 请求方和响应方间无法维护状态,都是一次性的,它不知道前后的请求都发生了什么。但有的场景下,我们需要维护状态。最典型的,一个用户登陆微博,发布、关注、评论,都应是在登录后的用户状态下的。「标记」那解决办法是什么呢?

在这里插入图片描述

<code>const express = require("express");

const session = require("express-session");

const MongoStore = require("connect-mongo");

const app = express();

app.use(

session({

secret: "this is session", // 服务器生成 session 的签名

resave: true,

saveUninitialized: true, //强制将为初始化的 session 存储

cookie: {

maxAge: 1000 * 60 * 10,// 过期时间

secure: false, // 为 true 时候表示只有 https 协议才能访问cookie

},

rolling: true, //为 true 表示 超时前刷新,cookie 会重新计时; 为 false 表示在超时前刷新多少次,都是按照第一次刷新开始计时。

store: MongoStore.create({

mongoUrl: 'mongodb://127.0.0.1:27017/lzm_session',

ttl: 1000 * 60 * 10 // 过期时间

}),

})

);

app.use((req,res,next)=>{

if(req.url==="/login"){

next()

return;

}

if(req.session.user){

req.session.garbage = Date();

next();

}else{

res.redirect("/login")

}

})

JSON Web Token (JWT)

(1)介绍

在这里插入图片描述

我为什么要保存这可恶的session呢, 只让每个客户端去保存该多好?

在这里插入图片描述

当然, 如果一个人的token 被别人偷走了, 那我也没办法, 我也会认为小偷就是合法用户, 这其实和一个人的session id 被别人偷走是一样的。

这样一来, 我就不保存session id 了, 我只是生成token , 然后验证token , 我用我的CPU计算时间获取了我的session 存储空间 !

解除了session id这个负担, 可以说是无事一身轻, 我的机器集群现在可以轻松地做水平扩展, 用户访问量增大, 直接加机器就行。 这种无状态的感觉实在是太好了!

缺点:

占带宽,正常情况下要比 session_id 更大,需要消耗更多流量,挤占更多带宽,假如你的网站每月有 10 万次的浏览器,就意味着要多开销几十兆的流量。听起来并不多,但日积月累也是不小一笔开销。实际上,许多人会在 JWT 中存储的信息会更多;无法在服务端注销,那么久很难解决劫持问题;性能问题,JWT 的卖点之一就是加密签名,由于这个特性,接收方得以验证 JWT 是否有效且被信任。对于有着严格性能要求的 Web 应用,这并不理想,尤其对于单线程环境。

注意:

CSRF攻击的原因是浏览器会自动带上cookie,而不会带上token;

以CSRF攻击为例:

cookie:用户点击了链接,cookie未失效,导致发起请求后后端以为是用户正常操作,于是进行扣款操作;

token:用户点击链接,由于浏览器不会自动带上token,所以即使发了请求,后端的token验证不会通过,所以不会进行扣款操作;

(2)实现

<code>//jsonwebtoken 封装

const jsonwebtoken = require("jsonwebtoken")

const secret = "lzm"

const JWT = {

generate(value,exprires){

return jsonwebtoken.sign(value,secret,{ expiresIn:exprires})

},

verify(token){

try{

return jsonwebtoken.verify(token,secret)

}catch(e){

return false

}

}

}

module.exports = JWT

//node中间件校验

app.use((req,res,next)=>{

// 如果token有效 ,next()

// 如果token过期了, 返回401错误

if(req.url==="/login"){

next()

return;

}

const token = req.headers["authorization"].split(" ")[1]

if(token){

var payload = JWT.verify(token)

// console.log(payload)

if(payload){

const newToken = JWT.generate({

_id:payload._id,

username:payload.username

},"1d")

res.header("Authorization",newToken)

next()

}else{

res.status(401).send({ errCode:"-1",errorInfo:"token过期"})

}

}

})

//生成token

const token = JWT.generate({

_id: result[0]._id,

username: result[0].username

}, "1d")

res.header("Authorization", token)

//前端拦截

/*

* @作者: liangzm

*/

import axios from 'axios'

// Add a request interceptor

axios.interceptors.request.use(function (config) {

const token = localStorage.getItem("token")

config.headers.Authorization = `Bearer ${ token}`

return config;

}, function (error) {

return Promise.reject(error);

});

// Add a response interceptor

axios.interceptors.response.use(function (response) {

const { authorization } = response.headers

authorization && localStorage.setItem("token",authorization)

return response;

}, function (error) {

const { status} = error.response

if(status===401){

localStorage.removeItem("token")

window.location.href="/login"code>

}

return Promise.reject(error);

});



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。