ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Midway 集成 Passport 认证:本地登录、JWT 与自定义策略完整实战指南

Midway 集成 Passport 认证:本地登录、JWT 与自定义策略完整实战指南 后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载身份验证是绝大多数 Web 应用的核心能力。Midway 框架将 Node.js 生态中最流行的认证中间件 Passport 封装为midwayjs/passport组件通过CustomStrategy装饰器与PassportStrategy/PassportMiddleware两个高阶函数把策略定义、认证中间件和控制器无缝接入 Midway 的依赖注入体系。读完本文你将掌握在 Midway 应用中落地本地账号密码认证、JWT 无状态认证以及任意第三方 OAuth 策略如 GitHub的完整方法并理解其底层执行链路。一、为什么选择 PassportPassport 之所以被广泛采用在于其设计哲学——认证通过可扩展的“策略”Strategy插件来完成。Passport 本身不挂载任何路由、不假设任何特定数据库也不替你决定用户数据的存取方式这使它的灵活性最大化把应用层面的决策权完全交还给开发者。Midway 在此基础上进一步做了面向 IoC控制反转的封装策略以类的方式注册进容器认证中间件通过装饰器与控制器绑定最终获得与框架一致的开发体验。从仓库源码可以看到整个封装的核心建立在两个高阶函数之上PassportStrategy(Strategy, name?)接收一个 Passport 原生策略类与可选名称返回一个继承AbstractStrategyWrapper的抽象子类供开发者派生具体的策略类PassportMiddleware(strategy)接收策略类或策略类数组返回一个继承AbstractPassportMiddleware的中间件抽象类。这两个函数的实现位于 packages/passport/src/passport/passport.service.ts是理解整个组件工作原理的关键入口。二、环境准备与安装1. 安装依赖$ npm i midwayjs/passport passport --save $ npm i types/passport --save-dev其中passport是认证核心库提供策略调度、会话管理、req.login/req.logout等底层能力types/passport提供 TypeScript 类型提示开发期使用。2. 开启 bodyparser 与 session如果实现的是表单/JSON 提交类认证如本地账号密码登录需要开启对应 Web 框架的bodyparser否则请求体无法被解析如果还希望在登录后维持会话状态需要一并启用session支持。仓库测试夹具中即有基于 packages/passport/test/fixtures/passport-express-session/src/configuration.ts 的会话场景示例可作对照。3. 注册组件在configuration.ts中将组件导入// configuration.ts import { join } from path; import * as jwt from midwayjs/jwt; import { ILifeCycle, } from midwayjs/core; import { Configuration } from midwayjs/core; import * as passport from midwayjs/passport; Configuration({ imports: [ jwt, passport, ], importConfigs: [join(__dirname, ./config)], conflictCheck: true, }) export class ContainerLifeCycle implements ILifeCycle {}组件在启动时通过 packages/passport/src/configuration.ts 中的PassportConfiguration完成初始化onReady阶段会从容器中获取单例PassportAuthenticator为后续策略注册做好准备。三、组件核心机制速览1. 默认配置midwayjs/passport内置一份默认配置packages/passport/src/config/config.default.tsexport const passport { session: true, assignProperty: true, sessionUserProperty: user, userProperty: user, };参数含义参数默认值说明sessiontrue是否启用会话登录状态保存关闭后每次请求都需重新认证assignPropertytrue认证成功后是否将用户对象赋值到指定属性sessionUserPropertyuser用户信息在 session 中存储的键名userPropertyuser认证成功后用户对象挂载到req/ctx上的属性名默认即req.user开启session后PassportAuthenticator的init阶段会自动注册一个名为session的内置策略实现见 packages/passport/src/passport/session.stratey.ts用于在后续请求中从会话恢复用户身份。2. 策略注册与装饰器CustomStrategy装饰器packages/passport/src/decorator/strategy.ts本质上是给类同时打上Scope(ScopeEnum.Singleton)与Provide()标记让自定义策略成为容器中的单例 Bean可被注入与复用。四、实战一本地账号密码认证1. 定义策略本地认证使用passport-local风格策略。通过CustomStrategy装饰器标记并派生PassportStrategy(Strategy)创建策略类// local-strategy.ts import { CustomStrategy, PassportStrategy } from midwayjs/passport; import { Repository } from typeorm; import { InjectEntityModel } from midwayjs/orm; import { UserEntity } from ./user; import * as bcrypt from bcrypt; CustomStrategy() export class LocalStrategy extends PassportStrategy(Strategy) { InjectEntityModel(UserEntity) userModel: RepositoryUserEntity; // 策略的验证 async validate(username, password) { const user await this.userModel.findOne({ username }); if (await bcrypt.compare(password, user.password)) { throw new Error(error password username); } return { username, password, }; } // 当前策略的参数 getStrategyOptions(): any { return {}; } }要点说明validate钩子负责获取认证有效负载如用户名/密码必须有返回值。它的参数并不固定取决于所使用策略的回调签名可通过展开符打印查看实际入参返回值语义返回对象时视为认证成功throw则视为失败getStrategyOptions返回传入原生策略构造函数的选项本地策略通常为空对象{}真实调用链PassportStrategy内部会在Init阶段创建原生策略实例new Strategy(this.getStrategyOptions(), cb)并包装validate为 Passport 标准的verify回调——validate返回对象时调用done(null, result)返回数组时展开为done(null, ...result)抛错时调用done(err, null)见 packages/passport/src/passport/passport.service.ts 的init方法。2. 派生认证中间件接下来派生PassportMiddleware(LocalStrategy)创建中间件// local-middleware.ts import { Inject, Provide } from midwayjs/core; import { PassportMiddleware } from midwayjs/passport; import { Context } from midwayjs/express; Provide() export class LocalPassportMiddleware extends PassportMiddleware(LocalStrategy) { // 设置 AuthenticateOptions getAuthenticateOptions(): Promisepassport.AuthenticateOptions | passport.AuthenticateOptions { return { failureRedirect: /login, presetProperty: user }; } }getAuthenticateOptions()返回的选项决定了认证成功/失败后的行为。常用选项定义见 packages/passport/src/interface.ts选项类型说明failureRedirectstring认证失败后重定向的 URLsuccessRedirectstring认证成功后重定向的 URLsuccessMessage/failureMessageboolean \| string是否在req.session.messages中记录成功/失败消息assignPropertystring将用户对象赋值到指定属性如usersessionboolean是否把登录状态写入会话默认继承全局配置authInfoboolean是否把认证附加信息写入req.authInfoscope/state/promptstring \| string[]OAuth 类策略的授权参数透传3. 在控制器中使用中间件// controller.ts import { Provide, Post, Inject, Controller } from midwayjs/core; Provide() Controller(/) export class LocalController { Post(/passport/local, { middleware: [LocalPassportMiddleware] }) async localPassport() { console.log(local user: , this.ctx.req.user); return this.ctx.req.user; } }4. 用 curl 验证curl -X POST http://localhost:7001/passport/local -d {username: demo, password: 1234} -H Content-Type: application/json 结果 {username: demo, password: 1234}中间件执行流程对应 packages/passport/src/passport/passport.service.ts 的authenticate方法合并全局配置与getAuthenticateOptions()的选项 → 从容器获取策略实例 → 调用PassportAuthenticator.authenticate逐个执行策略 → 根据successResult/redirectResult/failResult三种结果分别走成功回调、302 重定向或失败处理失败时若配置了failureRedirect则重定向否则默认抛出401 Unauthorized。五、实战二JWT 无状态认证1. 安装与配置先安装midwayjs/jwt$ npm i midwayjs/jwt然后在配置文件中写入密钥与过期时间export const jwt { secret: xxxxxxxxxxxxxx, // fs.readFileSync(xxxxx.key) expiresIn: 2d // 过期时间语法参考 vercel/ms }PS. JWT 默认未加密请不要把敏感信息存放在 payload 中。secret可以是字符串也可以从密钥文件中读取expiresIn支持ms库的时长语法如2d、1h、30s。2. 定义 JWT 策略JWT 策略基于passport-jwt使用ExtractJwt.fromAuthHeaderAsBearerToken()从Authorization: Bearer token请求头中提取令牌// strategy/jwt-strategy.ts import { CustomStrategy, PassportStrategy } from midwayjs/passport; import { Strategy, ExtractJwt } from passport-jwt; CustomStrategy() export class JwtStrategy extends PassportStrategy( Strategy, jwt ) { Config(jwt) jwtConfig; async validate(payload) { return payload; } getStrategyOptions(): any { return { secretOrKey: this.jwtConfig.secret, jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), }; } }这里PassportStrategy的第二个参数jwt为策略命名PassportAuthenticator.use(name, strategy)会以该名称注册见 packages/passport/src/passport/authenticator.ts 的use方法。validate(payload)收到的即是被解密校验后的 JWT payload可直接返回作为用户信息。3. 派生 JWT 中间件// jwt-middleware.ts import { Provide } from midwayjs/core; import { PassportMiddleware } from midwayjs/passport; import { JwtStrategy } from ./strategy/jwt-strategy; Provide() export class JwtPassportMiddleware extends PassportMiddleware(JwtStrategy) { getAuthenticateOptions(): Promisepassport.AuthenticateOptions | passport.AuthenticateOptions { return {}; } }4. 签发与校验接口import { Provide, Post, Inject } from midwayjs/core; import { Controller, Post } from midwayjs/core; import { Jwt } from midwayjs/jwt; Provide() Controller(/) export class JwtController { Inject() jwt: Jwt; Inject() ctx: any; Post(/passport/jwt, { middleware: [JwtPassportMiddleware] }) async jwtPassport() { console.log(jwt user: , this.ctx.req.user); return this.ctx.req.user; } Post(/jwt) async genJwt() { return { t: await this.jwt.sign({ msg: Hello Midway }), }; } }5. curl 全流程验证先请求签发接口拿到 tokencurl -X POST http://127.0.0.1:7001/jwt 结果 {t: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}再携带 token 访问受保护接口curl http://127.0.0.1:7001/passport/jwt -H Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 结果 {msg: Hello Midway,iat: 1635468727,exp: 1635468827}仓库测试夹具 packages/passport/test/fixtures/passport-express-jwt 与 packages/passport/test/fixtures/passport-koa-jwt 分别提供了 Express 与 Koa 下的完整 JWT 认证示例其策略实现passport-express-jwt/src/jwt.strategy.ts与上述写法一一对应可作为可运行参考。六、实战三自定义第三方策略以 GitHub OAuth 为例midwayjs/passport支持 Passport 官方策略库 中的任意策略封装方式完全一致。这里以 GitHub OAuth 为例。1. 安装策略包$ npm i passport-github2. 定义 GitHub 策略// github-strategy.ts import { CustomStrategy, PassportStrategy } from midwayjs/passport; import { Strategy, StrategyOptions } from passport-github; const GITHUB_CLIENT_ID xxxxxx, GITHUB_CLIENT_SECRET xxxxxxxx; CustomStrategy() export class GithubStrategy extends PassportStrategy(Strategy, github) { async validate(...payload) { return payload; } getStrategyOptions() { return { clientID: GITHUB_CLIENT_ID, clientSecret: GITHUB_CLIENT_SECRET, callbackURL: https://127.0.0.1:7001/auth/github/cb }; } }与本地/JWT 策略不同的是OAuth 策略通过validate(...payload)的展开参数接收完整回调信息通常包含accessToken、refreshToken与profilegetStrategyOptions中需按第三方平台要求填入clientID、clientSecret、callbackURL等 OAuth 应用参数。3. 派生中间件// github-middleware.ts import { PassportMiddleware } from midwayjs/passport; Provide() export class GithubPassportMiddleware extends PassportMiddleware { }不传策略参数时PassportMiddleware会按默认配置处理此时认证行为由控制器上挂载的中间件 策略名称约定共同决定。4. 定义 OAuth 路由// controller.ts import { Provide, Get, Inject } from midwayjs/core; Provide() Controller(/oauth) export class AuthController { Inject() ctx: any; Get(/github, { middleware: [GithubPassportMiddleware] }) async githubOAuth() {} Get(/github/cb, { middleware: [GithubPassportMiddleware] }) async githubOAuthCallback() { return this.ctx.req.user; } }OAuth 流程分为两步路由/oauth/github负责把用户重定向到 GitHub 授权页中间件内部产生redirectResult默认以 302 响应并设置Location头/oauth/github/cb是回调地址与getStrategyOptions中配置的callbackURL对应认证成功后在this.ctx.req.user中读取用户信息。七、底层执行链路与进阶能力1. 认证状态机PassportAuthenticator.authenticatepackages/passport/src/passport/authenticator.ts是核心调度器它遍历已注册策略为每个策略实例注入success/fail/redirect/pass/error五个动作策略在认证过程中必须且只能调用其中一个success(user, info)认证成功中断后续策略fail(challenge, status)认证失败记录失败原因后继续尝试下一个策略redirect(url, status)重定向到第三方授权页中断后续策略pass()不表态跳过error(err)内部错误直接抛出。多策略场景下失败会被累积在failures数组中最终汇总为failResult交给中间件统一处理。2. 会话能力序列化/反序列化策略类中可选实现serializeUser/deserializeUser/transformAuthInfo三个钩子PassportStrategy的init方法会将其分别注册为 session 序列化器、反序列化器与req.authInfo转换器登录/登出中间件通过attachRequestMethod为req注入login/logout/isAuthenticated/isUnauthenticated方法Koa 模式下会额外在ctx上暴露ctx.login、ctx.logout、ctx.isAuthenticated等别名会话恢复启用session: true后内置session策略packages/passport/src/passport/session.stratey.ts在后续请求中从req.session[userProperty].user取出序列化数据经deserializeUser还原为完整用户对象。3. Koa 适配Koa 的ctx与 Express 的req结构不同组件通过 packages/passport/src/passport/request.ts 中的createReqMock把ctx.state、Koa request、Node 原生req与ctx四者代理为一个模拟的 Expressreq对象从而复用同一套 Passport 逻辑同时把ctx.login、ctx.logout等桥接到req对应方法见 packages/passport/src/passport/passport.service.ts 中 Koa 分支。因此midwayjs/passport可同时适配 Express、Koa 与 WebEgg三种运行时仓库测试分别覆盖了 packages/passport/test/fixtures/passport-express、packages/passport/test/fixtures/passport-koa-jwt 等场景。4. 测试验证组件自带完整的认证测试packages/passport/test/index.test.ts覆盖了本地认证成功/失败401、会话保持登录、JWT 签发与校验等路径例如 Express 本地认证用例通过createHttpRequest模拟请求断言未携带凭据时 302 跳转/login、携带正确凭据时返回 200可直接作为二次开发的回归基准。八、小结midwayjs/passport以「策略类 认证中间件 控制器绑定」三层结构把 Passport 的灵活性完整继承进 Midway 的 IoC 体系本地认证CustomStrategyPassportStrategy(Strategy)PassportMiddleware(LocalStrategy)配合validate钩子校验账号密码JWT 认证passport-jwt策略 midwayjs/jwt签发令牌实现无状态接口鉴权第三方 OAuth引入任意 Passport 策略包getStrategyOptions填入平台参数即可复用统一底座会话序列化、Koa/Express 双适配、失败重定向与 401 兜底等能力由组件统一承载。按照上述模式社区中所有 Passport 策略如 Google、Facebook、微信、钉钉等都可以在数分钟内接入你的 Midway 应用。赞分享后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载相关推荐Feathers 认证实战指南用 CLI 快速集成 JWT、本地账号与 OAuth 登录Feathers 认证实战指南用 CLI 快速集成 JWT、本地账号与 OAuth 登录 导读 本文围绕 FeathersThe API and real后端Web框架Passport-JWT基于JSON Web Tokens的Passport认证策略Passport JWT基于JSON Web Tokens的Passport认证策略 项目基础介绍及编程语言 Passport JWT是由CSDN公司开发的I后端InsForge 认证 API 完全指南JWT 会话、管理员登录与 OAuth 集成实战InsForge 认证 API 完全指南JWT 会话、管理员登录与 OAuth 集成实战 本文基于 InsForge 开源仓库中的《Insforge OSS人工智能AI Agent自主智能体工具调用交互助手AI 评测上一篇Selenium Wire证书管理自定义CA证书与HTTPS解密的最佳实践下一篇推荐一款强大的Windows剪贴板工具win32yank创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表