Skip to content

Repository files navigation

@cqut-openproject/cas-sdk

TypeScript 7+ Node.js 18+ pnpm 10+ License: MIT

Note

@cqut-openproject/cas-sdk 是面向 TypeScript 与 JavaScript 跨运行时生态的重庆理工大学统一身份认证(UIS / CAS)客户端 SDK,提供跨运行时、零外部强依赖、强类型的认证流转、密码加密与票据验证能力。

Caution

本 SDK 在登录期间需使用学校账号与密码请求 UIS 服务端。凭据仅在客户端内存流转,请严格遵循密码学安全与隐私合规要求,切勿在不安全的日志中打印明文凭据。

主要特性

  • 「跨运行时」:原生兼容 Node.js (>= 18)、Cloudflare Workers (Edge)、AWS Lambda / Vercel (Serverless)、Bun 与现代浏览器环境
  • 「零外部依赖」:纯 TypeScript 原生 BigInt 实现 RSA PKCS#1 v1.5 加密与 XML 验证解析,产物体积极小(< 10 KB)
  • 「网络层解耦」:采用控制反转(IoC)架构,支持按需注入 Node fetchundiciaxios 或自定义代理实例
  • 「双层 API」:提供开箱即用的一站式 login / safeLogin 流转方法与精细化的分步原子 API
  • 「生产级防御」:内置防 XXE、防 Doctype 实体注入、64KB 响应体积上限防御与网络瞬态自动重试

安装

方式一:通过 Git Release 分支 / Tag 安装(推荐,无需 Token / 免配置)

仓库内置 CI 会在发版与更新时自动将包含编译产物(dist/)的版本同步至 release 分支与 v* Tag。下游项目无需配置任何 Token 或 .npmrc,可直接安装:

# 持续跟随最新稳定构建
pnpm add github:CQUT-OpenProject/CAS-SDK#release

# 或锁定具体版本 Tag(例如 v1.0.0)
pnpm add github:CQUT-OpenProject/CAS-SDK#v1.0.0
# 或使用 npm / yarn
npm install github:CQUT-OpenProject/CAS-SDK#release

方式二:通过 GitHub Packages 安装

如需通过 npm 官方包名格式引入,请在项目根目录或全局 ~/.npmrc 中配置:

@cqut-openproject:registry=https://npm.pkg.github.com

然后执行安装:

pnpm add @cqut-openproject/cas-sdk
# 或使用 npm / yarn
npm install @cqut-openproject/cas-sdk

快速使用

1. 一键登录并获取 Ticket

import { createCasClient } from "@cqut-openproject/cas-sdk";

await using client = createCasClient();

const result = await client.login({
  account: "2021123456",
  password: "YourPasswordHere",
  serviceUrl: "https://example.cqut.edu.cn/auth/callback",
  validate: true, // 可选:获取 Ticket 后自动完成服务端验证
});

console.log("Service Ticket:", result.ticket);
console.log("Verified User:", result.validation?.user);

2. 函数式 Result 模式安全登录

import { createCasClient, isCasErrorOfKind } from "@cqut-openproject/cas-sdk";

await using client = createCasClient();

const result = await client.safeLogin({
  account: "2021123456",
  password: "YourPasswordHere",
  serviceUrl: "https://example.cqut.edu.cn/auth/callback",
});

if (result.ok) {
  console.log("Service Ticket:", result.data.ticket);
} else {
  if (isCasErrorOfKind(result.error, "AUTH_FAILED")) {
    console.error("账号或密码错误");
  } else {
    console.error("登录失败:", result.error.message);
  }
}

3. 注入自定义网络实现 (Fetcher)

Node.js / Undici(绑定 Dispatcher 强制 IPv4)

import { CasClient } from "@cqut-openproject/cas-sdk";
import { fetch as undiciFetch, Agent } from "undici";
import dns from "node:dns";

const ipv4Dispatcher = new Agent({
  connect: {
    lookup: (hostname, options, callback) => {
      dns.lookup(hostname, { family: 4, all: false }, callback);
    },
  },
});

const client = new CasClient({
  fetcher: async (req) => {
    return undiciFetch(req.url, {
      method: req.method,
      headers: req.headers,
      body: req.body,
      redirect: req.redirect,
      signal: req.signal,
      dispatcher: ipv4Dispatcher,
    });
  },
});

Axios 适配器

import { CasClient } from "@cqut-openproject/cas-sdk";
import axios from "axios";

const client = new CasClient({
  fetcher: async (req) => {
    const res = await axios.request({
      url: req.url,
      method: req.method,
      headers: req.headers,
      data: req.body,
      maxRedirects: req.redirect === "manual" ? 0 : 5,
      validateStatus: () => true,
      responseType: "text",
    });

    return {
      status: res.status,
      statusText: res.statusText,
      headers: res.headers as Record<string, string | string[]>,
      text: async () => (typeof res.data === "string" ? res.data : JSON.stringify(res.data)),
      json: async () => (typeof res.data === "string" ? JSON.parse(res.data) : res.data),
    };
  },
});

4. 原子 API:密码加密

import { CasClient, getSecretParam } from "@cqut-openproject/cas-sdk";

// 独立密码加密
const secretParam = CasClient.encryptPassword("MyPassword123");
// 或直接调用函数
const encoded = getSecretParam("MyPassword123");

错误处理

SDK 统一抛出强类型 CasError,可通过 isCasErrorOfKinderror.kind 进行分类处理:

import { CasClient, CasError, isCasErrorOfKind } from "@cqut-openproject/cas-sdk";

try {
  await client.login({ ... });
} catch (err) {
  if (isCasErrorOfKind(err, "AUTH_FAILED")) {
    console.error("账号或密码错误");
  } else if (isCasErrorOfKind(err, "CAPTCHA_REQUIRED")) {
    console.error("触发验证码校验");
  } else if (isCasErrorOfKind(err, "NETWORK_ERROR")) {
    console.error("网络瞬态错误或连接超时");
  } else if (isCasErrorOfKind(err, "UPSTREAM_ERROR")) {
    console.error("UIS 服务端异常 (500/502/503)");
  } else if (isCasErrorOfKind(err, "VALIDATION_FAILED")) {
    console.error("Ticket 验证未通过");
  }
}

许可证

本项目基于 MIT 协议开源。

About

统一身份认证的独立 TypeScript 客户端 SDK

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages