node 之 身份认证(cookie,session,token<jwt>)
对于服务端渲染和前后端分离这两种开发模式来说,分别有着不同的身份认证方案:
.服务端渲染推荐使用 Session 认证机制 (SessIon也会用到cookie)
前后端分离推荐使用 jwt 认证机制
cookie (保存在浏览器上)
简单案例
//导入模块
const express = require("express"); const path = require("path"); const cookieParser = require("cookie-parser");
//创建服务 const app = express(); app.listen("8001", () => { console.log("服务已开启"); }); // 应用级配置使用cookie-parser app.use(cookieParser()); //应用级配置 app.use(express.urlencoded({ extended: false })); //登录页面 app.get("/login.html", (req, res) => { res.sendFile(path.join(__dirname, "public", "login.html")); }); //登录提交的接口 app.post("/api/login", (req, res) => { if (req.body.username === "admin" && req.body.password === "123") { res.cookie("isLogin", 1, { maxAge: 2 * 1000 }); res.send(`<script>alert('登录成功');location.href="/index.html";</script>`); } else { res.send(`<script>alert('登录失败');location.href="/login.html";</script>`); } }); //后台首页 app.get("/index.html", (req, res) => { if (req.cookies && req.cookies.isLogin === "1") { res.sendFile(path.join(__dirname, "public", "index.html")); } else { res.send(`<script>alert('登录失败');location.href="/login.html";</script>`); } });
有效期
默认:浏览会话结束(也就是关闭浏览器)
设置有效期:res.cookie('isLogin',1,{maxAge:毫秒数})
优缺点:
优点:
体积小
客户端存放,不占用服务器空间
浏览器会自动携带,不需要写额外的代码,比较方便
缺点
客户端保存,安全性较低,但是可以存放加密的字符窜来解决
可以实现跨域,但是难度大,难理解,代码难度高
不适合前后端分离的开发
适用场景
传统的服务器渲染模式
存储安全性较低的数据,比如视频的存放位置等
session (保存在服务器上)
简单案例
//导入模块
const express = require("express"); const path = require("path"); // const cookieParser = require("cookie-parser"); const session = require("express-session"); const app = express(); app.listen("8001", () => { console.log("服务已开启"); }); // 应用级配置使用cookie-parser // app.use(cookieParser()); //应用级配置 app.use(express.urlencoded({ extended: false })); app.use( session({ secret: "123", //这个随便写,第二次进行加密 saveUninitialized: false, resave: false, }) ); //登录页面 app.get("/login.html", (req, res) => { res.sendFile(path.join(__dirname, "public", "login.html")); }); //登录提交的接口 app.post("/api/login", (req, res) => { console.log(req.body); if (req.body.username === "admin" && req.body.password === "123") { // res.cookie("isLogin", 1, { maxAge: 2 * 1000 }); req.session.isLogin = 1; res.send(`<script>alert('登录成功');location.href="/index.html";</script>`); } else { res.send(`<script>alert('登录失败');location.href="/login.html";</script>`); } }); //后台首页 app.get("/index.html", (req, res) => { if (req.session && req.session.isLogin === 1) { console.log("这个session是有数据的"); } // if (req.cookies && req.cookies.isLogin === "1") { // res.sendFile(path.join(__dirname, "public", "index.html")); // } else { // res.send(`<script>alert('登录失败');location.href="/login.html";</script>`); // } });
有效期
默认:浏览会话结束(也就是关闭浏览器)
优缺点:
优点:
服务端存放,安全性高
浏览器会自动携带cookie,不需要写额外的代码,比较方便
适合服务器端渲染模式
缺点
占用服务器端空间
session实现离不开cookie,如果禁用cookie,session不好实现
不适合前后端分离的开发
适用场景
传统的服务器渲染模式
安全性要求比较高的数据可以使用session存放,比如用户私密信息,验证码等
JWT(token) json web token
注意:数据持久化 : localStorage 可以存储 token
原理分析
1.前端提交用户名和密码,服务端验证
2.服务端验证通过,生成token,返回给前端
3.前端自行保存token(localstorage)
4.登录成功后,每次请求要在请求头带上Authorization,只是token
简单案例
//express-jwt 模块用于解密 'token' 字符串 //规范:解密token, //1.unless:如果没有unless方法,则默认所有接口都需要验证,unless把不要验证的接口排除掉 //2.secret:加密秘钥 //3.algorithms:加密算法 ['HS256'] //4.path 取值范围, //---字符串表示排除一个地址,如'/api/login' //---数组:表示排除多个地址,如['/api/login',''] //---正则:表示排除符合规则的地址,如/^\/api/(排除以/api开头的接口) //jsonwebtoken 模块用于加密 , 还可以控制哪些接口需要身份认证 //规范: //1.token:'bearer '+jwt.sign(要保存的信息,秘钥,配置项) //2.expiresIn 值是字符串时为毫秒,值是数字时为秒 //导入模块 const express = require("express"); const jwt = require("jsonwebtoken"); const expressJWT = require("express-jwt"); //创建服务 const app = express(); app.listen("8001", () => { console.log("服务已经开启"); }); //应用级配置 app.use(express.urlencoded({ extended: false })); //用于token验证应用级配置 app.use( expressJWT({ secret: "bigevent-970", algorithms: ["HS256"], }).unless({ path: /^\/api/ }) ); //请求 app.post("/api/login", (req, res) => { console.log(req.body); if (req.body.username === "admin" && req.body.password === "123") { res.json({ status: 0, msg: "登录成功", token: "bearer " + jwt.sign({ username: "admin", age: 20 }, "bigevent-970", { expiresIn: 20, }), }); } else { res.json({ status: 1, msg: "登录失败", }); } }); //用去用户信息 app.get("/my/getUser", (req, res) => { res.json({ status: 0, msg: "获取信息成功", data: { name: "admin", age: 18, }, }); });
优缺点:
优点:
token由客户端保存,不会占用服务器空间
缺点
客户端发送请求的时候,需要手动编写代码,携带token
适用场景
适合前后端分离的开发模式