前端保存登录信息-jwt的使用

node+express开发中,经常会使用后端session+前端cookie方式来保存登录信息,如果后端采用多服务器的话,session要共享还得采用redis来保存session。而session多少还是有一些存储和计算开销的;另外前端,用cookie来存放sessionid或者其他一些登录信息,而一些禁用了cookie的场景,或者一些本身就不是浏览器的应用的话,在cookie中保存登录信息就不太适用了。

这种情况下,可以考虑采用jwt存本地存储方式来对应。

以下给出一个简单的例子。

通过nginx反向代理发布,nginx.conf里相关配置是这样的:

lua 复制代码
        location /app/ {
            proxy_pass    http://jwtdemo.dgiij.org:3000/;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
	        }

后端服务js

javascript 复制代码
const express = require('express')
const app = express()
const jwt = require('jsonwebtoken')
var { expressjwt: ejwt }  = require('express-jwt')
const jwtSecretKey= 'ParisOlympics2024';
const jwtexpiresIn= '12h'
const app_prefix="https://jwtdemo.dgiij.org/app"
const loginurl="https://jwtdemo.dgiij.org/app/login.html&redurl="
var localusers = require("./localusers.json");

app.use("/", express.static("html/app"));
app.use("/pub", express.static("html/pub"));

app.use(ejwt({ secret: jwtSecretKey, algorithms: ["HS256"]}).unless({ path: [/^\/login/,/^\/pub/,/^\/index/] }))

app.use(function (err, req, res, next) {
	if (err.name === 'UnauthorizedError') {
		let redurl=app_prefix+ req.originalUrl;  
		res.redirect(loginurl+redurl);
		}
})

app.post('/login',express.json(), (req, res) => {
	let obj=req.body;
	let matchuser=localusers.find(item=>((item.userid==obj.uid)&&(item.password==obj.upw)));
	if (matchuser!=undefined) { 
		let clientip=req.header("x-forwarded-for")?req.header("x-forwarded-for"):req.ip;
		let userinfo={"userid":matchuser.userid,"username":matchuser.username,"login_ip":clientip}
		let token = jwt.sign(userinfo, jwtSecretKey, { expiresIn: jwtexpiresIn})
		res.json({ "code": 200, "jwt": token })
		}
	else { res.json({ "code": 401, "msg": '登录失败' }) }
})
 
app.get('/getuserinfo', (req, res) => {
	res.json({ "code": 200, userinfo: req.auth })
})

app.listen(3000, console.log('server is running on port 3000'))

前端登录页面(html/app/login.html):

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>jwt demo login</title>
<script src="pub/axios.min.js"></script>
<script src="pub/jquery-3.6.1.min.js"></script>
</head>

<body>
	<input type="text" id="uid" name="uid" placeholder="用户名">
	<input type="password" id="upw" name="upw" placeholder="密码">
	<button>账号密码登录</button>
</body>
<script>
let reg = new RegExp("(^|&)" + "redurl" + "=([^&]*)(&|$)","i");
var redurl = location.search.substr(1).match(reg);

$("#login").click(()=>{ 
	if ((document.getElementById("uid").value.trim()=="")||(document.getElementById("upw").value.trim()=="")) { alert("请输入用户名和密码!"); }
	else {
		let nuid=document.getElementById("uid").value.trim().toLowerCase();
		axios.post("/app/login",{"uid": nuid,"upw": document.getElementById("upw").value.trim()}).then(resp=>{
			let obj=resp.data;
			if (obj.code==200) {
				localStorage.setItem("jwt", obj.jwt);
				document.location=((redurl==null)?"/app/index.html":redurl[2]);
				}
			else { alert(obj.msg); }
			}).catch(errp2 => { console.log(errp2); alert("app服务错"); });
		}
	});

</script>
</html>

前端app页面(html/app/index.html):

html 复制代码
<!DOCTYPE html>
<html lang="en">
 
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jwt demo app</title>
<script src="pub/axios.min.js"></script>
<script src="pub/jquery-3.6.1.min.js"></script>
</head>
 
<body>
<span>&nbsp;&nbsp;当前会话用户:</span>
<span name="loginname" id="loginname"></span>
<br>
<br>

</body>
<script>
	axios.defaults.headers.common['Authorization'] ='Bearer ' + localStorage.getItem('jwt');
	axios.get("/app/getuserinfo").then(res=>{
		let obj=res.data;
		document.getElementById("loginname").innerHTML = obj.userinfo.username ;
		}).catch(errp => { console.log(errp); alert("app服务错,请稍后再刷新页面"); });
</script>
</html>
相关推荐
Hyyy11 分钟前
很多Desktop都在上的Computer Use是什么
前端·llm
慢功夫13 分钟前
开篇:VS Code 为什么不是一个普通 React App
前端·visual studio code
你挚爱的强哥24 分钟前
Vue2 实现 1.5s 十连击监听(连续点击若干次),封装通用可复用点击检测工具,不用 data!Vue 封装通用连击监听方法,支持自定义时长与点击次数
前端·javascript·vue.js
程序员张328 分钟前
SpringBoot集成BCrypt密码加密库
java·spring boot·后端
CaffeinePro35 分钟前
FastAPI数据库集成SQLAlchemy异步ORM全方案
后端·fastapi
小旭Coding38 分钟前
凌晨告警轰炸!Go 服务协程只增不减,内存持续暴涨直至 OOM
后端
半个落月41 分钟前
用 LangChain.js 手写一个能读写文件和执行命令的 Mini Cursor
javascript·人工智能·后端
天外天-亮1 小时前
HBuilder X 使用 uview-plus 方式
开发语言·javascript·hbuilder x·uview-plus
huashengzsj1 小时前
Shopify个人建站如何搭建独立站:从零开始的完整指南
前端·网络·人工智能
程序猿小泓1 小时前
从 Claude Code 学 Agent Harness:一个前端工程师的 AI Agent 学习笔记
前端·人工智能·学习