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

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

Node.js单点登录SSO详解:Session、JWT、CORS让登录更简单(一):https://developer.aliyun.com/article/1628445


三、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;
    }
    // 生成token
    const 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.query
    if (!appId) {
        return res.send('请输入appId')
    }
    // 判断是否登录
    if (req.session.userName) {
        let token
        if (appToMapUrl[appId].token) {
            // 获取token
            token = appToMapUrl[appId].token
        } else {
            // 生成token
            token = getToken(appId)
            // 存入appToMapUrl
            appToMapUrl[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.body
    if (username === 'admin' && password === '123456') {
        const token = getToken(appId);
        // 存入appToMapUrl
        appToMapUrl[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>


目录
相关文章
|
8月前
|
前端开发 JavaScript 安全
HTML+CSS+JS密码灯登录表单
通过结合使用HTML、CSS和JavaScript,我们创建了一个带有密码强度指示器的登录表单。这不仅提高了用户体验,还帮助用户创建更安全的密码。希望本文的详细介绍和代码示例能帮助您在实际项目中实现类似功能,提升网站的安全性和用户友好性。
141 3
|
9月前
|
存储 JSON JavaScript
Node.js单点登录SSO详解:Session、JWT、CORS让登录更简单(一)
Node.js单点登录SSO详解:Session、JWT、CORS让登录更简单(一)
302 0
|
2月前
|
人工智能 前端开发 JavaScript
webpack-dev-server代理后端一直报CORS跨域或500错误
在Vue项目中使用Webpack的devServer代理后端接口时,遇到500错误。问题根源在于浏览器请求中携带的Origin头导致服务器报错,而Postman测试正常。通过分析发现,调整或移除Origin头可解决问题。解决办法包括:1) 在代理配置中添加正确的Origin头;2) 删除请求中的Origin头。文章还深入解析了Origin头的作用及changeOrigin配置的实际意义,并附带相关文档链接,帮助开发者更好地理解与解决类似跨域问题。
144 12
|
4月前
|
前端开发 JavaScript 应用服务中间件
前端跨域问题解决Access to XMLHttpRequest at xxx from has been blocked by CORS policy
跨域问题是前端开发中常见且棘手的问题,但通过理解CORS的工作原理并应用合适的解决方案,如服务器设置CORS头、使用JSONP、代理服务器、Nginx配置和浏览器插件,可以有效地解决这些问题。选择合适的方法可以确保应用的安全性和稳定性,并提升用户体验。
2310 90
|
4月前
|
JSON 缓存 前端开发
对CORS(跨域)的一些见解
CORS(跨域资源共享)是W3C标准,用于解决AJAX跨源请求限制。浏览器与服务器需共同支持CORS,浏览器自动处理请求头,开发者无需额外操作。CORS分为简单请求与非简单请求:简单请求满足特定条件(如方法为GET/POST/HEAD且头信息有限制),浏览器直接发送;非简单请求需先进行“预检”请求(OPTIONS方法),确认服务器允许后才发送实际请求。服务器回应需包含Access-Control-Allow-Origin等字段,以控制跨域访问权限。
133 10
|
10月前
|
JSON 安全 前端开发
浅析CORS跨域漏洞与JSONP劫持
浅析CORS跨域漏洞与JSONP劫持
392 3
|
8月前
|
开发框架 中间件 Java
如何处理跨域资源共享(CORS)的 OPTIONS 请求?
处理 CORS 的 OPTIONS 请求的关键是正确设置响应头,以告知浏览器是否允许跨域请求以及允许的具体条件。根据所使用的服务器端技术和框架,可以选择相应的方法来实现对 OPTIONS 请求的处理,从而确保跨域资源共享的正常进行。
400 61
|
9月前
|
JSON 前端开发 安全
CORS 是什么?它是如何解决跨域问题的?
【10月更文挑战第20天】CORS 是一种通过服务器端配置和浏览器端协商来解决跨域问题的机制。它为跨域资源共享提供了一种规范和有效的方法,使得前端开发人员能够更加方便地进行跨域数据交互。
|
7月前
|
安全 Java 应用服务中间件
SpringBoot:CORS是什么?SpringBoot如何解决跨域问题?
CORS是Web开发中常见且重要的机制,SpringBoot通过提供注解、全局配置和过滤器等多种方式来解决跨域问题。选择适合的方式可以帮助开发者轻松处理跨域请求,提高应用的灵活性和安全性。
347 2
|
8月前
|
安全
CORS 跨域资源共享的实现原理是什么?
CORS 跨域资源共享的实现原理是什么?

热门文章

最新文章