当前位置: 首页 > news >正文

Node.js单点登录SSO详解:Session、JWT、CORS让登录更简单

文章目录

      • 一、SSO介绍
        • 1、使用SSO的好处
      • 二、中间件介绍
        • 1、Express
          • 安装
          • 导入
          • 使用
        • 2、cors
          • 安装
          • 导入
          • 配置
        • 3、express-session
          • 安装
          • 导入
          • 配置
          • 使用
        • 4、jsonwebtoken
          • 安装
          • 导入
          • 使用
        • 5、jwt和session对比
      • 三、SSO实现方案
        • 1、安装依赖
        • 2、结构
        • 3、实现原理
      • 三、示例代码
        • 1、nodejs端 server/index.js
        • 2、vueA项目app.vue
        • 3、vueB项目app.vue
        • 4、登录页面login.html

一、SSO介绍

单点登录(Single Sign On),简称为 SSO,是比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

在这里插入图片描述

如图所示,图中有4个系统,分别是Application1、Application2、Application3、和SSO。Application1、Application2、Application3没有登录模块,而SSO只有登录模块,没有其他的业务模块,当Application1、Application2、Application3需要登录时,将跳到SSO系统,SSO系统完成登录,其他的应用系统也就随之登录了。这完全符合我们对单点登录(SSO)的定义。

1、使用SSO的好处
  • 方便用户 用户使用应用系统时,能够一次登录,多次使用。用户不再需要每次输入用户名称和用户密码,也不需要牢记多套用户名称和用户密码。单点登录平台能够改善用户使用应用系统的体验。
  • 方便管理员 系统管理员只需要维护一套统一的用户账号,方便、简单。相比之下,系统管理员以前需要管理很多套的用户账号。每一个应用系统就有一套用户账号,不仅给管理上带来不方便,而且,也容易出现管理漏洞。
  • 简化应用系统开发 开发新的应用系统时,可以直接使用单点登录平台的用户认证服务,简化开发流程。单点登录平台通过提供统一的认证平台,实现单点登录。因此,应用系统并不需要开发用户认证程序。

在这里插入图片描述

二、中间件介绍

1、Express

Express 是一个保持最小规模的灵活的 Node.js Web 应用程序开发框架,为 Web 和移动应用程序提供一组强大的功能。

安装
npm install express
导入
const express = require('express')
使用
const express = require('express')
const app = express()
const port = 3000app.get('/', (req, res) => {res.send('Hello World!')
})app.post('/', (req, res) => {res.send('Got a POST request')
})app.listen(port, () => {console.log(`Example app listening on port ${port}`)
})
2、cors

cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件,可以很方便地解决跨域问题。

CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列 HTTP 响应头组成,这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源。

安装
npm install cors
导入
const cors = require('cors')
配置
  • 启用所有 CORS 请求
app.use(cors())
  • 指定URL配置
app.use(cors({ origin: 'http://127.0.0.1:5500' }))
  • 为单个路由启用 CORS
app.get('/data', cors(), (req, res) => {res.json({name: 'cors in node.js',language: 'JavaScript',server: 'Express.js',})
})
  • 使用选项配置 CORS
const options = {origin: 'http://127.0.0.1:5500',methods: 'GET, PUT',
}
app.use(cors(options))
  • 使用函数配置动态 CORS 源
const options = {origin: dynamicConfiguration(),methods: 'GET, PUT',
}const dynamicConfiguration = async (req) => {const db = getDB() // simulating database objectlet origin = await db.getOrigin(req.headers) //simulating fetching origin from DB based on the headersreturn origin
}app.use(cors(options))
3、express-session

express-session中间件将会话数据存储在服务器上;它仅将会话标识(而非会话数据)保存在 cookie 中。从1.5.0版本开始, express-session不再依赖cookie-parser,直接通过req/res读取/写入;默认存储位置内存存储(服务器端)

安装
npm install express-session
导入
const session = require('express-session')
配置
app.use(session({secret: 'YOUR_SESSION_SECRET',//加密字符串。 使用该字符串来加密session数据,自定义resave: false,//强制保存session即使它并没有变化saveUninitialized: true,//强制将未初始化的session存储。当新建了一个session且未设定属性或值时,它就处于未初始化状态。cookie: {maxAge: 30 * 60 * 1000}
}))
使用
//设置
req.session.userName = userName;
//获取
const userName = req.session.userName
4、jsonwebtoken

JSON Web Token(JWT)是一种用于在web上传递信息的标准,它以JSON格式表示信息,通常用于身份验证和授权。

JWT由三个部分组成:Header(头部)、Payload(负载)和Signature(签名)。它们用点号分隔开,形成了一个JWT令牌。

在现代web应用中,用户身份认证是非常重要且必不可少的一环。而使用Node.js和Express框架,可以方便地实现用户身份认证。而在这个过程中,jsonwebtoken这个基于JWT协议的模块可以帮助我们实现安全且可靠的身份认证机制,可以让我们轻松地生成、解析和验证JWT。

安装
npm install jsonwebtoken
导入
const jwt = require('jsonwebtoken')
使用
// 生成token
const token = jwt.sign({id: 'appId',name: 'zhangsan',secret: 'YOUR_SECRET_KEY'
}, '123456', {expiresIn: '2h'
})//验证token
jwt.verify(token, 'shhhhh', (err, decoded) => {if (err) {console.error('无效的令牌');} else {// 使用解码后的令牌数据console.log(decoded);}
});
5、jwt和session对比
对比因素JWTSession
存储存储在客户端,不需要服务器保持会话状态。存储在服务器,需要服务器维护会话信息。
安全性加密较严密,但如果token被窃取,攻击者可以任意使用。如果sessionID被窃取,攻击者可以冒充用户登陆。
性能在每次请求时需要验证和解码token,性能较差。只需查找sessionID就能获取会话信息,性能较好。
扩展性在多服务器或者跨域环境中更易扩展。在多服务器环境中需要同步session,扩展性较差。
数据大小JWT的大小比sessionID大,因此需要更多的带宽。sessionID大小稳定,对带宽需求较小。
到期时间可以为每个token设置不同的过期时间。所有session的过期时间通常相同。
客户端存储位置可以存储在Cookie, LocalStorage, SessionStorage中存储在Cookie中。
跨域问题无跨域问题,且对于移动应用而言友好。跨域问题复杂,需要服务器支持CORS。
状态无状态,服务器不需要保存用户信息。有状态,服务器需要保存用户信息。
使用场景用于认证和信息交换,尤其适合单页应用(SPA)和前后端分离的项目。主要用于记录用户状态,适配传统的后端渲染的Web服务。

三、SSO实现方案

1、安装依赖

启动服务:express
操作cookie:express-session
生成token:jsonwebtoken
解决跨域:cors

npm install express
npm install express-session
npm install jsonwebtoken
npm install cors
2、结构

vueA项目:使用vite创建项目
vueB项目:使用vite创建项目
nodejs端:server/index.js
登录页面:login.html

3、实现原理
  • 用户首次访问系统A或B时,需要进行登录。
  • 系统统A或B带着appId信息重定向登录页面。
  • 认证系统验证用户登录信息。
  • 验证通过后,设置session值,用户返回一个token。
  • 认证系统带着token重定向给系统A或B,得知用户是已登录状态。
  • 系统A或B正常进入系统。
  • 用户再访问另一个系统时。
  • 通过session值,得知用户是已登录状态。
  • 认证系统带着token重定向给系统。
  • 系统正常进入系统。

在这里插入图片描述

三、示例代码

1、nodejs端 server/index.js
import express from "express"
import session from 'express-session'
import fs from "node:fs"
import cors from "cors"
import jwt from 'jsonwebtoken'// 应用列表
const appToMapUrl = {'fd8xIoDC': {url: 'http://localhost:5173',name: 'appA',secret: '123456',token: ''},'DDkq0YYh': {url: 'http://localhost:5174',name: 'appB',secret: '789102',token: ''}
}// 创建服务器
const app = express()// 解析post请求体
app.use(express.json())// 跨域
app.use(cors())// 创建session配置项,注册为express-session中间件
app.use(session({secret: '123456',//加密字符串。 使用该字符串来加密session数据,自定义resave: false,//强制保存session即使它并没有变化saveUninitialized: true,//强制将未初始化的session存储。当新建了一个session且未设定属性或值时,它就处于未初始化状态。cookie: {maxAge: 30 * 60 * 1000}
}))//获取token
const getToken = (appId) => {const appInfo = appToMapUrl[appId]if (!appInfo) {return null;}// 生成tokenconst token = jwt.sign({id: appId,name: appInfo.name,secret: appInfo.secret}, '123456', {expiresIn: 60 * 60})return token;
}//是否登录
app.get('/login', (req, res) => {const {appId} = req.queryif (!appId) {return res.send('请输入appId')}// 判断是否登录if (req.session.userName) {let tokenif (appToMapUrl[appId].token) {// 获取tokentoken = appToMapUrl[appId].token} else {// 生成tokentoken = getToken(appId)// 存入appToMapUrlappToMapUrl[appId].token = token}// 跳转res.redirect(`${appToMapUrl[appId].url}?token=${token}`)return;} else {// 读取登录页面const html = fs.readFileSync('./login.html', 'utf-8')res.send(html)}
})// 解析表单数据
app.use(express.urlencoded({ extended: true }));// 登录
app.post('/protected', (req, res) => {const {username,password,appId} = req.bodyif (username === 'admin' && password === '123456') {const token = getToken(appId);// 存入appToMapUrlappToMapUrl[appId].token = token;//存入session,证明已经登录req.session.userName = username;res.redirect(`${appToMapUrl[appId].url}?token=${token}`)} else {res.send('用户名或密码错误')}
})// 监听端口
app.listen(3000, () => {console.log('http://localhost:3000')
})
2、vueA项目app.vue
<script setup lang="ts">
const token = location.search.split('token=')[1]
if (!token) {fetch('http://localhost:3000/login?appId=fd8xIoDC').then(res => {location.href = res.url})
} else {localStorage.setItem('token', token)
}
</script><template><div>这里是appA</div></template><style scoped>
</style>
3、vueB项目app.vue
<script setup>
const token = location.search.split('token=')[1]
if (!token) {fetch('http://localhost:3000/login?appId=DDkq0YYh').then(res => {location.href = res.url})
} else {localStorage.setItem('token', token)
}
</script><template><div>这里是appB</div>
</template><style scoped>
</style>
4、登录页面login.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>登录</title>
</head>
<body><div><h1>登录页面</h1><form action="/protected" method="post"><input type="text" name="username"><input type="password" name="password"><input type="hidden" name="appId"><input type="submit" value="登录"></form></div><script>const appId = location.search.split('?')[1].split('=')[1]document.querySelector('input[name="appId"]').value = appId</script>
</body>
</html>

相关文章:

Node.js单点登录SSO详解:Session、JWT、CORS让登录更简单

文章目录 一、SSO介绍1、使用SSO的好处 二、中间件介绍1、Express安装导入使用 2、cors安装导入配置 3、express-session安装导入配置使用 4、jsonwebtoken安装导入使用 5、jwt和session对比 三、SSO实现方案1、安装依赖2、结构3、实现原理 三、示例代码1、nodejs端 server/ind…...

提高Java应用稳定性的部署实践

提高Java应用稳定性的部署实践 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在实际的Java开发过程中&#xff0c;应用的稳定性是一个至关重要的问题。无论是…...

简过网:考公务员报班和不报班的区别大吗?

备考公务员&#xff0c;究竟是报班还是不报班呢&#xff1f;一篇文章让你看看两者之间的区别&#xff01; 报不报班&#xff0c;其实这是很多考生都会纠结的地方&#xff0c;其实小编还是建议报个班的&#xff0c;这不仅仅是因为我是做这个行业的&#xff0c;更是因为这么长时…...

文化财经盘立方通达信期货通支撑压力自动画线多空转折指标公式源码

文化财经盘立方通达信期货通支撑压力自动画线多空转折指标公式源码&#xff1a; N:26; M:2; D:5; TR1:MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW)); ATR:MA(TR1,N); MEDIANN:(HIGH LOW)/2; UP:MEDIANNATR*M; DN:MEDIANN-ATR*M; A:BARSLAST(C…...

重生之我要学后端11--数据库基础概念(持续更新)

数据库 前言一、关系型数据库二、非关系型数据库三、应用场景关系型数据库&#xff08;RDBMS&#xff09;非关系型数据库&#xff08;NoSQL&#xff09;综合因素 前言 后端开发者应该熟悉数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;包括关系型数据库&#xff08;…...

配置 Cmder 到鼠标右键

win Q 快捷键搜索 cmd&#xff0c;以管理员身份运行 在命令行输入 cmder.exe /REGISTER ALL...

kali下安装使用蚁剑(AntSword)

目录 0x00 介绍0x01 安装0x02 使用1. 设置代理2. 请求头配置3. 编码器 0x00 介绍 蚁剑&#xff08;AntSword&#xff09;是一个webshell管理工具。 官方文档&#xff1a;https://www.yuque.com/antswordproject/antsword 0x01 安装 在kali中安装蚁剑&#xff0c;分为两部分&am…...

GIT-LFS使用

0.前言 目前git仓库有很多很大的文件需要管理&#xff0c;但是直接上传&#xff0c;每次clone的文件太大&#xff0c;所有准备使用git-lfs解决。 1、下载和安装 Git LFS 1.1、直接下载二进制包&#xff1a; Releases git-lfs/git-lfs GitHub 安装 Git LFS sudo rpm -ivh…...

免费分享一套SpringBoot+Vue在线水果(销售)商城管理系统【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue在线水果(销售)商城管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue在线水果(销售)商城管理系统 Java毕业设计_哔哩哔哩_bilibili【免费】SpringBootVue在线水果(销售)商…...

推荐两款电脑文件处理工具,强大到你不舍得卸载

EasyFileCount EasyFileCount是一款基于Java开发的多功能文件管理工具&#xff0c;旨在帮助用户更轻松地管理和优化他们的文件存储。以下是EasyFileCount的主要功能和特点&#xff1a; 查看文件夹大小&#xff1a;用户可以快速统计和查看文件夹的总大小&#xff0c;实时显示各…...

Python 高级实战:基于自然语言处理的情感分析系统

前言 在大数据和人工智能迅猛发展的今天&#xff0c;自然语言处理&#xff08;NLP&#xff09;作为人工智能的重要分支&#xff0c;已经深入到我们的日常生活和工作中。情感分析作为NLP中的一个重要应用&#xff0c;广泛应用于市场分析、舆情监控和客户反馈等领域。本文将讲述…...

ruby面试题

ruby 基础 1、each、map、collect的区别 each: 仅遍历数组&#xff0c;并做相应操作&#xff0c;数组本身不发生改变。 map:遍历数组&#xff0c;并做相应操作后&#xff0c;返回新数组(处理)&#xff0c;原数组不变。 collect: 跟map作用一样。 collect! map!: 多了一个作…...

Android U Settings 应用中 APN 菜单实现的代码逻辑

功能简介 MobileNetwork移动网络设置页面下有【接入点设置】(APN)。 问题:为什么Controller初始化找不到pref,然后报错。 Note:什么时候切换成Controller的呢?在Android T&U 上还没有更新成kt实现 ,但是已经有Controller的方案。 流程逻辑 1、界面“telephony_a…...

java时间处理工具类

效果 最近7天&#xff1a;2024年6月21日-2024年6月27日过去一周、最近一周&#xff1a;2024年6月16日-2024年6月22日过去三个月&#xff1a;2024年3月-2024年6月近半年、过去半年&#xff1a;2023年12月-2024年6月去年&#xff1a;2023年1月-2023年12月过去3年&#xff1a;202…...

Android高级面试_2_IPC相关

Android 高级面试-3&#xff1a;语言相关 1、Java 相关 1.1 缓存相关 问题&#xff1a;LruCache 的原理&#xff1f; 问题&#xff1a;DiskLruCache 的原理&#xff1f; LruCache 用来实现基于内存的缓存&#xff0c;LRU 就是最近最少使用的意思&#xff0c;LruCache 基于L…...

docker封禁对外端口映射

docker比linux防火墙规则优先级要高&#xff0c;一旦在docker里面配置了对外服务端口的话在iptable里面封不掉&#xff0c;需要通过下面的方法进行封禁&#xff1a; 这里我的宿主机IP地址是10.5.1.244,docker 内部网络ip段是默认的172.17段的&#xff0c;以下为命令&#xff1…...

【leetcode系列】567.字符串的排列(滑动窗口)

题目 给你两个字符串 s1 和 s2 &#xff0c;写一个函数来判断 s2 是否包含 s1 的排列。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 换句话说&#xff0c;s1 的排列之一是 s2 的 子串 。 示例 示例 1&#xff1a; 输入&#xff1a;s1 “ab” s2…...

情感分析方法与实践

第1关&#xff1a;情感分析的基本方法 情感分析简介 情感分析&#xff0c;又称意见挖掘、倾向性分析等。简单而言&#xff0c;是对带有情感色彩的主观性文本进行分析、处理、归纳和推理的过程。在日常生活中&#xff0c;情感分析的应用非常普遍&#xff0c;下面列举几种常见的…...

迁移学习——CycleGAN

CycleGAN 1.导入需要的包2.数据加载&#xff08;1&#xff09;to_img 函数&#xff08;2&#xff09;数据加载&#xff08;3&#xff09;图像转换 3.随机读取图像进行预处理&#xff08;1&#xff09;函数参数&#xff08;2&#xff09;数据路径&#xff08;3&#xff09;读取文…...

【软件测试】对于测试中的bug,我们真正了解了吗?

目录 1.软件测试的生命周期 1.1.软件测试阶段流程 1.2.各流程的任务 2.什么是bug 2.1.bug的概念 2.2.怎么描述bug 2.3.bug的级别 2.4.bug的生命周期 1.软件测试的生命周期 在学习bug前&#xff0c;我们先来学习一下软件测试的生命周期&#xff0c;也就是测试人员进行测…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...