0

0

如何用Node.js实现一个支持OAuth2的授权服务器?

betcha

betcha

发布时间:2025-10-05 08:50:03

|

952人浏览过

|

来源于php中文网

原创

首先实现授权码流程,通过OAuth2orize处理授权请求与令牌发放,结合Passport进行用户认证;接着配置客户端认证与会话管理,最后提供登录及授权确认页面,完成标准OAuth2授权码流程。

如何用node.js实现一个支持oauth2的授权服务器?

实现一个支持 OAuth2 的授权服务器,核心是处理授权码流程、令牌发放、客户端认证和用户身份验证。Node.js 结合 OAuth2orizePassport 是常见选择。下面是一个基础但完整的实现思路和代码示例。

1. 初始化项目并安装依赖

创建项目目录并安装必要模块:

npm init -y
npm install express oauth2orize passport passport-local bcrypt body-parser cookie-session

这些库的作用:

  • express:构建 Web 服务
  • oauth2orize:实现 OAuth2 授权服务器逻辑
  • passport + passport-local:处理用户登录认证
  • body-parser:解析请求体
  • cookie-session:管理会话(用于登录状态)
  • bcrypt:密码加密

2. 配置 OAuth2orize 授权服务器

创建 server.js,初始化 Express 和 OAuth2orize:

const express = require('express');
const oauth2orize = require('oauth2orize');
const bodyParser = require('body-parser');
const session = require('cookie-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');

const app = express();
const server = oauth2orize.createServer();

// 中间件
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(session({ secret: 'your-session-secret', maxAge: 3600000 }));
app.use(passport.initialize());
app.use(passport.session());

// 模拟数据存储(生产环境应使用数据库)
const clients = [
  { id: 'client_id_123', secret: 'client_secret_456', redirectUri: 'http://localhost:3000/callback' }
];

const tokens = [];
const codes = [];
const users = [{ id: 1, username: 'user', password: '$2b$10$...' }]; // 密码哈希

// Passport 用户本地认证
passport.use(new LocalStrategy((username, password, done) => {
  const user = users.find(u => u.username === username);
  if (user && bcrypt.compareSync(password, user.password)) {
    return done(null, user);
  }
  return done(null, false);
}));

passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => {
  const user = users.find(u => u.id === id);
  done(null, user);
});

3. 实现 OAuth2 授权端点

配置授权码(authorization code)流程:

GentleAI
GentleAI

GentleAI是一个高效的AI工作平台,为普通人提供智能计算、简单易用的界面和专业技术支持。让人工智能服务每一个人。

下载
// 生成授权码
server.grant(oauth2orize.grant.code((client, redirectUri, user, ares, done) => {
  const code = Math.random().toString(36).substr(2, 8);
  codes.push({
    value: code,
    clientId: client.id,
    redirectUri: redirectUri,
    userId: user.id
  });
  done(null, code);
}));

// 交换令牌
server.exchange(oauth2orize.exchange.code((client, code, redirectUri, done) => {
  const authCode = codes.find(c => c.value === code);
  if (!authCode) return done(null, false);

  if (client.id !== authCode.clientId) return done(null, false);
  if (redirectUri !== authCode.redirectUri) return done(null, false);

  const token = Math.random().toString(36).substr(2, 24);
  tokens.push({
    value: token,
    userId: authCode.userId,
    clientId: client.id
  });

  done(null, token);
}));

// 授权中间件:检查客户端合法性
function authenticateClient(req, res, next) {
  const clientId = req.body.client_id || req.query.client_id;
  const clientSecret = req.body.client_secret;
  const client = clients.find(c => c.id === clientId && c.secret === clientSecret);
  if (!client) return res.status(401).json({ error: 'Invalid client' });
  req.oauth2 = { client };
  next();
}

// GET /authorize - 用户确认授权页面
app.get('/authorize', server.authorize((clientId, redirectUri, done) => {
  const client = clients.find(c => c.id === clientId);
  if (!client) return done(new Error('Unknown client'));
  if (client.redirectUri !== redirectUri) return done(new Error('Invalid redirect URI'));
  return done(null, client, redirectUri);
}), (req, res) => {
  res.render('dialog', { transactionID: req.oauth2.transactionID, user: req.user, client: req.oauth2.client });
});

// POST /authorize/decision - 处理用户同意/拒绝
app.post('/authorize/decision', server.decision());

// POST /token - 获取访问令牌
app.post('/token', authenticateClient, server.token(), server.errorHandler());

4. 用户登录与授权确认页面

添加简单视图(可用模板引擎如 EJS 或直接返回 HTML):

app.get('/login', (req, res) => {
  res.send(`
    <form action="/login" method="post">
      <input type="text" name="username" placeholder="用户名" /><br>
      <input type="password" name="password" placeholder="密码" /><br>
      <button type="submit">登录</button>
    </form>
  `);
});

app.post('/login', passport.authenticate('local', { failureRedirect: '/login' }), (req, res) => {
  // 登录成功后重定向到授权确认页
  res.redirect('/authorize?client_id=' + req.query.client_id + '&response_type=code&redirect_uri=' + encodeURIComponent(req.query.redirect_uri));
});

5. 启动服务器

```javascript app.listen(3000, () => { console.log('OAuth2 授权服务器运行在 http://localhost:3000'); }); ```

基本上就这些。这个例子实现了标准的授权码流程:

  • 客户端跳转到 /authorize 请求授权
  • 用户登录并确认授权
  • 服务器返回授权码
  • 客户端用授权码请求 /token 换取访问令牌

注意:这只是一个教学示例。生产环境需要加入更多安全措施,比如 HTTPS、CSRF 防护、刷新令牌、令牌过期、数据库持久化、PKCE 扩展等。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Node.js后端开发与Express框架实践
Node.js后端开发与Express框架实践

本专题针对初中级 Node.js 开发者,系统讲解如何使用 Express 框架搭建高性能后端服务。内容包括路由设计、中间件开发、数据库集成、API 安全与异常处理,以及 RESTful API 的设计与优化。通过实际项目演示,帮助开发者快速掌握 Node.js 后端开发流程。

425

2026.02.10

cookie
cookie

Cookie 是一种在用户计算机上存储小型文本文件的技术,用于在用户与网站进行交互时收集和存储有关用户的信息。当用户访问一个网站时,网站会将一个包含特定信息的 Cookie 文件发送到用户的浏览器,浏览器会将该 Cookie 存储在用户的计算机上。之后,当用户再次访问该网站时,浏览器会向服务器发送 Cookie,服务器可以根据 Cookie 中的信息来识别用户、跟踪用户行为等。

6500

2023.06.30

document.cookie获取不到怎么解决
document.cookie获取不到怎么解决

document.cookie获取不到的解决办法:1、浏览器的隐私设置;2、Same-origin policy;3、HTTPOnly Cookie;4、JavaScript代码错误;5、Cookie不存在或过期等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

368

2023.11.23

阻止所有cookie什么意思
阻止所有cookie什么意思

阻止所有cookie意味着在浏览器中禁止接受和存储网站发送的cookie。阻止所有cookie可能会影响许多网站的使用体验,因为许多网站使用cookie来提供个性化服务、存储用户信息或跟踪用户行为。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

447

2024.02.23

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

97

2025.08.19

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

336

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

776

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

97

2025.08.19

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号