温州行业网站建设,如何用手机制作游戏,学做网站要什么基础,2017 wordpress宽屏主题文章目录 一、SSO介绍1、使用SSO的好处 二、中间件介绍1、Express安装导入使用 2、cors安装导入配置 3、express-session安装导入配置使用 4、jsonwebtoken安装导入使用 5、jwt和session对比 三、SSO实现方案1、安装依赖2、结构3、实现原理 三、示例代码1、nodejs端 server/ind… 文章目录 一、SSO介绍1、使用SSO的好处 二、中间件介绍1、Express安装导入使用 2、cors安装导入配置 3、express-session安装导入配置使用 4、jsonwebtoken安装导入使用 5、jwt和session对比 三、SSO实现方案1、安装依赖2、结构3、实现原理 三、示例代码1、nodejs端 server/index.js2、vueA项目app.vue3、vueB项目app.vue4、登录页面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.userName4、jsonwebtoken
JSON Web TokenJWT是一种用于在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 操作cookieexpress-session 生成tokenjsonwebtoken 解决跨域cors
npm install express
npm install express-session
npm install jsonwebtoken
npm install cors2、结构
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 langts
const token location.search.split(token)[1]
if (!token) {fetch(http://localhost:3000/login?appIdfd8xIoDC).then(res {location.href res.url})
} else {localStorage.setItem(token, token)
}
/scripttemplatediv这里是appA/div/templatestyle scoped
/style3、vueB项目app.vue
script setup
const token location.search.split(token)[1]
if (!token) {fetch(http://localhost:3000/login?appIdDDkq0YYh).then(res {location.href res.url})
} else {localStorage.setItem(token, token)
}
/scripttemplatediv这里是appB/div
/templatestyle scoped
/style4、登录页面login.html
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title登录/title
/head
bodydivh1登录页面/h1form action/protected methodpostinput typetext nameusernameinput typepassword namepasswordinput typehidden nameappIdinput typesubmit value登录/form/divscriptconst appId location.search.split(?)[1].split()[1]document.querySelector(input[nameappId]).value appId/script
/body
/html