TypeScript设计模式:策略模式

策略模式(Strategy Pattern)是一种行为设计模式,用于定义一系列算法,让它们可以相互替换,并且算法的变化不会影响使用算法的客户端。在身份认证系统中,策略模式常用于支持多种认证方式(如JWT、Basic Auth),以实现灵活性和可扩展性。

设计模式原理

策略模式通过将变化的算法部分提取到独立的策略类中,由上下文类动态选择和执行具体策略。这样可以实现:

  • 单一职责:每个策略类只负责一种算法实现,上下文负责协调。
  • 灵活性:支持运行时切换算法,无需修改上下文代码。
  • 开闭原则:对扩展开放(新增策略),对修改关闭(上下文不变)。

在 TypeScript 中,策略模式通过接口和多态实现,确保类型安全和代码清晰。

策略模式的结构

策略模式包含以下角色:

  1. Strategy(策略接口) :定义算法的公共接口,如 authenticate()
  2. ConcreteStrategy(具体策略) :实现策略接口,提供具体算法。
  3. Context(上下文) :维护策略对象的引用,通过接口调用算法。

优点

  • 解耦合:算法与上下文分离,降低耦合度。
  • 可扩展性:新增算法只需添加新策略类。
  • 类型安全:TypeScript 的类型系统确保接口一致性。

身份认证中的策略模式

在身份认证系统中(如 Passport.js),策略模式用于支持多种认证方式。例如:

  1. JWT认证:通过验证JSON Web Token来确认用户身份。
  2. Basic Auth:通过用户名和密码进行认证。
  3. OAuth:通过第三方服务(如Google、GitHub)进行认证。

以下以身份认证为例,展示策略模式如何支持动态选择认证方式,类似 Passport.js 的机制。

TypeScript 实现示例:身份认证中的策略模式

以下是一个身份认证系统的实现,动态选择认证策略(如JWT、Basic Auth)来验证用户请求。

typescript 复制代码
// 策略接口
interface AuthStrategy {
  authenticate(credentials: any): Promise<boolean>;
  getUserInfo(): string;
}

// 具体策略:JWT 认证
class JwtStrategy implements AuthStrategy {
  async authenticate(credentials: { token: string }): Promise<boolean> {
    // 模拟 JWT 验证逻辑
    if (credentials.token.startsWith("jwt_")) {
      return true; // 假设 token 以 "jwt_" 开头表示有效
    }
    throw new Error("无效的 JWT Token");
  }

  getUserInfo(): string {
    return "JWT 用户: user@example.com";
  }
}

// 具体策略:Basic Auth 认证
class BasicAuthStrategy implements AuthStrategy {
  async authenticate(credentials: { username: string; password: string }): Promise<boolean> {
    // 模拟 Basic Auth 验证逻辑
    if (credentials.username === "admin" && credentials.password === "pass123") {
      return true;
    }
    throw new Error("无效的用户名或密码");
  }

  getUserInfo(): string {
    return "Basic Auth 用户: admin";
  }
}

// 具体策略:OAuth 认证
class OAuthStrategy implements AuthStrategy {
  async authenticate(credentials: { accessToken: string }): Promise<boolean> {
    // 模拟 OAuth 验证逻辑
    if (credentials.accessToken.startsWith("oauth_")) {
      return true; // 假设 accessToken 以 "oauth_" 开头表示有效
    }
    throw new Error("无效的 OAuth Access Token");
  }

  getUserInfo(): string {
    return "OAuth 用户: oauth_user@example.com";
  }
}

// 上下文类:认证上下文
class AuthContext {
  private strategy: AuthStrategy;

  constructor(strategy: AuthStrategy) {
    this.strategy = strategy;
  }

  setStrategy(strategy: AuthStrategy): void {
    this.strategy = strategy;
  }

  async authenticate(credentials: any): Promise<string> {
    try {
      const isAuthenticated = await this.strategy.authenticate(credentials);
      if (isAuthenticated) {
        return this.strategy.getUserInfo();
      }
      return "认证失败";
    } catch (error) {
      return `认证错误: ${(error as Error).message}`;
    }
  }
}

// 客户端代码
async function main() {
  // 创建上下文并设置 JWT 策略
  let context = new AuthContext(new JwtStrategy());
  console.log(await context.authenticate({ token: "jwt_valid_token" })); // 输出: JWT 用户: user@example.com
  console.log(await context.authenticate({ token: "invalid_token" })); // 输出: 认证错误: 无效的 JWT Token

  // 切换到 Basic Auth 策略
  context.setStrategy(new BasicAuthStrategy());
  console.log(await context.authenticate({ username: "admin", password: "pass123" })); // 输出: Basic Auth 用户: admin
  console.log(await context.authenticate({ username: "admin", password: "wrong" })); // 输出: 认证错误: 无效的用户名或密码

  // 切换到 OAuth 策略
  context.setStrategy(new OAuthStrategy());
  console.log(await context.authenticate({ accessToken: "oauth_valid_token" })); // 输出: OAuth 用户: oauth_user@example.com
}

main();

运行结果

运行以上代码,将输出:

sql 复制代码
JWT 用户: user@example.com
认证错误: 无效的 JWT Token
Basic Auth 用户: admin
认证错误: 无效的用户名或密码
OAuth 用户: oauth_user@example.com

为什么使用策略模式?

在身份认证系统中(如 Passport.js),认证逻辑因方式不同而变化(如JWT解析、Basic Auth验证、OAuth回调)。使用策略模式:

  • 动态切换:无需修改认证上下文代码,只需注入新策略。
  • 扩展性:新增认证方式(如SAML、OpenID)只需实现新策略类。
  • 可测试性:每个策略独立,便于单元测试。

其他适用场景

虽然本示例聚焦身份认证,策略模式在认证系统中还可用于:

  • 令牌解析:不同类型的令牌(如JWT、API Key)使用不同解析逻辑。
  • 权限检查:根据用户角色或认证方式应用不同权限验证规则。
  • 日志记录:不同认证方式记录不同格式的日志。

总结

策略模式在身份认证系统中通过封装可互换的认证算法(如JWT、Basic Auth、OAuth),提供了动态选择和扩展机制。TypeScript 的类型系统确保策略接口的一致性,而认证上下文的示例展示了如何通过策略模式实现灵活的认证逻辑。这使得系统能够轻松适应多种认证需求,同时保持代码的可维护性和扩展性。

相关推荐
brzhang2 小时前
为什么说低代码谎言的破灭,是AI原生开发的起点?
前端·后端·架构
得物技术2 小时前
破解gh-ost变更导致MySQL表膨胀之谜|得物技术
数据库·后端·mysql
小桥风满袖2 小时前
极简三分钟ES6 - ES9中字符串扩展
前端·javascript
小码编匠2 小时前
WPF 中的高级交互通过右键拖动实现图像灵活缩放
后端·c#·.net
小Wang3 小时前
npm私有库创建(docker+verdaccio)
前端·docker·npm
用户73087011793083 小时前
Vue中集成文字转语音:使用Web Speech API实现功能
前端
李重楼3 小时前
前端性能优化之 HTTP/2 多路复用
前端·面试
Java水解3 小时前
【MySQL】从零开始学习MySQL:基础与安装指南
后端·mysql
yanessa_yu3 小时前
全屏滚动网站PC端自适应方案
前端