使用 Authing 快速实现一套类似 OpenAI 的认证、API Key 商业权益授权机制

news2024/11/19 13:42:14

如果你有经常使用 OpenAI 或者 HuggingFace 这一类面向开发者的 SaaS 服务,对于 API Key 肯定不会陌生。我们在使用这些服务时,通常都会在其平台上面创建一套 API Key,之后我们才能在代码中通过这一串 API key 访问其服务;同时,我们购买的权益也会和对应的 API Key 绑定在一起。


除了 API Key 的校验,用户认证也是重要的一环,如果能够快速集成市面上常见的社会化登录方式(如微信、GitHub、Google 等),这将会极大降低用户使用的门槛。而大模型服务往往需要快速上线,快速强占市场,从零开发一套完整的用户认证体系无疑会消耗大量的时间和人力成本。

这篇文章我们关注的问题是:假如你也有这样一个面向开发者的大模型服务,我们如何基于 Authing强大的认证以及数据资源能力,快速实现你的认证和 API Key 模块。

01.5 分钟、5 行代码完成用户认证

一个比较完备且用户体验良好的登录框,应该能够支持以下几个基本的认证方式:账密登录、手机号验证码登录、常见社会化登录;如果是有公众号推广需求的服务,可能还需要关注公众号登录。而这些能力,Authing 的 Guard 全部都内置好了,不需要进行任何的开发工作。

首先第一步,我们需要在 Authing 创建一个用户池,这里我们将用户池类型设置为 ToC:

接下来在 Authing 控制台的应用 - 自建应用页面创建一个应用:这里我们选择「标准 Web 应用」,并且填好应用名称和二级域名:

创建好之后,你将会自动拥有一个能够被立即在线访问到的登录页面。接下来要做的,就是在这上面配置你需要的登录方式了:在应用详情的「登录控制」菜单,你可以快速添加你需要的认证方式:

我们以微信扫码登录这个方式举例:我们提供了非常完整的文档,你只需要按照文档的说明,填入相关的 AppId、AppSecret 即可:

配置完成再次访问登录页面,就可以看到微信扫码登录已经出现在界面上了!That's It!

如果你对于登录页面有品牌化的需求,比如自定义背景、自定义 CSS 等,也可以在 Authing 控制台的品牌化页面进行自定义:

接下来我们测试一下登录:用一个账号登录之后,你会看到页面跳转到了一个欢迎界面,这个是一个默认的调试页面,这里面介绍了后续你需要完成的操作:
如果你遇到了「无权限登录,请联系管理员」的错误提示,可以在 Authing 控制台的安全设置 - 通用安全 - 注册安全页面,将「禁止注册」开关关闭,以及在应用详情的访问授权页面,设置应用访问控制规则为「所有人可访问」。


请重点关注「处理回调」这部分的内容:相信你也已经猜到了,实际我们业务上线的时候,是需要替换这个默认的调试页面成你自己的回调地址的,「处理回调」这部分介绍了后续你需要完成的内容:

1. 替换回调地址;
2. 在回调地址接收 Authing 传过来的授权码 code;
3. 使用 code 换取用户信息和 token 并存储 token;
4. 后续此用户请求你的 API 时,需要携带上此 token;
5. 在后端校验此 token 的合法性。

如果你希望将登录页面嵌入到你自己的页面中,我们也提供了 React、Vue、Angular 以及 iOS、Android 的组件:

02.实现大模型 API Key 的调用鉴权

如本文最开始介绍的:大模型服务一般都会通过 API Key 的方式,允许用户通过可编程的方式接入你的大模型服务,以 OpenAI 举例,我们都知道在 Python 程序中我们是这么去使用的:

import openai

# 设置 API Key
openai.api_key = 'xxxxxxxxxxxxxxxxxxxxxx';

# 接下来去请求 OpenAI 的相关接口


这里面背后的逻辑,是 OpenAI 的 Python SDK 在请求 OpenAI 接口的时候,会在请求头上携带此 token,然后在后端校验此 Token 的合法性以及权益。


下面我们介绍如何使用 Authing 的数据资源能力来实现这两部分功能:API Key 的鉴权、API Key 的权益校验。
创建权限空间
第一步,我们在 Authing 控制台的「权限管理」-「权限空间」菜单创建一个名为 apikey 的权限空间,我们使用这个空间来存储和管理平台所有的 API Key。

创建 API Key 数据资源
假设我们想象你的开发者在你的平台上面创建了一个 API key,这个 key 可能会包含以下基本的信息:

  • key 的展示名称;
  • key 的内容:一串随机的且唯一的字符串;
  • key 的创建时间、修改时间、最近一次使用时间等等相关的元数据;
  • key 对应的权益信息,比如最多运行调用多少次 API、已经调用了多少次 API 等。


与之对应的,Authing 提供的了「数据资源」的概念,完美契合这样的场景。我们在 Authing 控制台的「权限管理」-「数据资源权限」菜单创建一个示例的字符串类型的「数据资源」:

  • 资源名称:对应 key 的展示名称;
  • 资源 Code:一串随机的且唯一的字符串,对应 key 的内容;
  • 字符串 Value:用于存储 key 相关的所有相关信息,随着你后续业务的增长,你可能会需要存储更多的信息:
{
 "CREATED": "2023.10.22 10:00:00",
 "LAST_USED": "2023.10.22 20:00:00",
 "TOTAL_USAGE": 123,
 "USAGE_AVALIABLE": 1000
}

除了控制台之外,我们也提供了相关的 API 和 SDK,帮助你在程序中自动创建 API Key(数据资源),下面以 nodejs sdk 为例:

import { ManagementClient } from "authing-node-sdk";

// 初始化 ManagementClient
const managementClient = new ManagementClient({
    accessKeyId: "AUTHING_ACCESS_KEY_ID", // Authing Access Key ID
    accessKeySecret: "AUTHING_ACCESS_KEY_SECRET", // Authing Access Key Secret
});

const resource = await managementClient.createDataResource({
 "namespaceCode": "apikey",
 "resourceName": "My API Key",
 "resourceCode": "fizePoEnkNrvWPwOxeYPdbQjoFXJfppDtm",
 "type": "STRING",
 "struct": '{"CREATED": "2023.10.22 10:00:00", "LAST_USED": "2023.10.22 20:00:00", "TOTAL_USAGE": 123, "USAGE_AVALIABLE": 1000}',
 "actions": [revoke]
})
console.log(resource)

给用户授权 API Key 数据资源
假如你在通过 Authing 来管理用户,我们推荐在创建好 API Key 之后,将这个 API Key 授权给对应的用户,这样你可以在 Authing 平台清晰得看到所有用户的 API Key 授权情况。如果你只是使用 Authing 的数据资源来做 API Key 管理,而不使用 Authing 来管理用户,此部分可跳过。

在 Authing 控制台的「权限管理」 - 「数据资源权限」菜单,点击右上角的「授权」按钮,我们先创建一个针对之前创建的 API Key 的数据策略:

接着将这个数据策略授权给某个用户:

在这里我们之所以使用数据策略这种将数据资源打包的方式来对用户进行授权,是为了后续的扩展性和可维护性,比如你可能还会需要给某个角色统一授权某一些打包在一起的资源,当用户订阅到期之后,将其移除出角色,这样就可以自动取消授权。

之后,你就可以看到这个用户已经被授权了这个 API Key 了:

同样的,除了控制台之外,我们也提供了相关的 API 和 SDK,下面以 nodejs sdk 为例:

import { ManagementClient } from "authing-node-sdk";

// 初始化 ManagementClient
const managementClient = new ManagementClient({
  accessKeyId: "AUTHING_ACCESS_KEY_ID", // Authing Access Key ID
  accessKeySecret: "AUTHING_ACCESS_KEY_SECRET", // Authing Access Key Secret
});

// 创建数据策略
const dataPolicy = await managementClient.createDataPolicy({
  policyName: "APIKEY_AUTHZ",
  statementList: [
    {
      effect: "ALLOW",
      permissionList: [
        {
          resourceCode: "fizePoEnkNrvWPwOxeYPdbQjoFXJfppDtm",
          operationType: "ALL"
        },
      ],
      namespaceCode: "apikey",
    },
  ]
});

// 授权数据策略
await managementClient.authorizeDataPolicy({
    policyIds: [dataPolicy.id],
    targetList: [
        {
 type: "USER",
            id: "user_id"
        }
    ]
})

// 获取用户权限列表
const userPermissionList = await managementClient.getUserPermissionList({
 "userIds": ["user_id"]
}

在项目代码中使用
下面我们将以 Node.js 的 NestJS Web 框架举例。

假设你需要用户在请求你的 API 时,在 x-myllm-apikey 请求头上需要带上 API Key,我们封装一个 NestJS 的 Guard,在这里完成 API Key 的校验逻辑:

从请求头中获取 x-myllm-apikey 的内容;

判断此 API Key 对应的数据资源是否存在,如果不存在,返回 false;

import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
import { ManagementClient } from "authing-node-sdk";

// 初始化 ManagementClient
const managementClient = new ManagementClient({
  accessKeyId: "AUTHING_ACCESS_KEY_ID", // Authing Access Key ID
  accessKeySecret: "AUTHING_ACCESS_KEY_SECRET", // Authing Access Key Secret
});

@Injectable()
export class AuthGuard implements CanActivate {
 constructor() {}

 async canActivate(context: ExecutionContext): Promise<boolean> {
 const apiKey = request.headers['x-myllm-apikey'];
 const existsRes = await managementClient.checkDataResourceExists({
        namespaceCode: "apikey",
        resourceCode: apiKey
    });
 return existsRes.data.exists;
}


接着在对应的接口中,应用此 Guard 即可:

@UseGuards(AuthGuard)
@Post('/my-api')
public async handleApi() {}

03.实现大模型 API Key 不同商业版本的权益和权限控制


假如说你的大模型服务有以下几种订阅版本:

订阅版本Rate Limit可用的 Token 数其他权益明细
免费版3 / s50000...
基础版10 / s500000...
企业版UnlimitedUnlimited...

你可以借助 Authing 的数据资源能力,将 API Key 对应的所有权益全部存储起来:比如 TOTAL_USAGE(已经使用的 token 数)、USAGE_AVALIABLE(可用的 Token 数),以及其他任何你需要存储的数据。

你可以调用 Authing 数据资源的创建、查询、修改、删除 API,对这些 API Key 进行管理。


比如我们修改一下上一节的 AuthGuard 的实现,这里我们加入了可用 Token 数的权益校验逻辑:

获取数据资源的详情;

在这里例子中我们在数据资源的内容里面添加了两个自定义字段 USAGE_AVALIABLE和 TOTAL_USAGE,所以我们的判断依据就是比较以下这两个大小即可。如果说你的业务系统有其他的判断规则,你也可以写任意的自定义逻辑。

import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
import { ManagementClient } from "authing-node-sdk";

// 初始化 ManagementClient
const managementClient = new ManagementClient({
  accessKeyId: "AUTHING_ACCESS_KEY_ID", // Authing Access Key ID
  accessKeySecret: "AUTHING_ACCESS_KEY_SECRET", // Authing Access Key Secret
});

@Injectable()
export class AuthGuard implements CanActivate {
 constructor() {}

 async canActivate(context: ExecutionContext): Promise<boolean> {
    const apiKey = request.headers['x-myllm-apikey'];
    const existsRes = await managementClient.checkDataResourceExists({
        namespaceCode: "apikey",
        resourceCode: apiKey
    });
 return existsRes.data.exists;
 if (!existsRes.data.exists) {
 return false
    }
    const { data: resource } = await managementClient.getDataResource({
        namespaceCode: "apikey",
        resourceCode: apiKey
    })
    const { struct } = resource;
    const apiKeyData = JSON.parse(struct);
 
    const { TOTAL_USAGE, USAGE_AVALIABLE } = apiKeyData;
 return USAGE_AVALIABLE > TOTAL_USAGE
  }
}


如果你需要在每次请求之后增加一下 TOTAL_USAGE 的值,你只需要调用修改数据资源的接口即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1155174.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

qt5工程打包成可执行exe程序

一、编译生成.exe 1.1、在release模式下编译生成.exe 1.2、建一个空白文件夹package&#xff0c;再将在release模式下生成的.exe文件复制到新建的文件夹中package。 1.3、打开QT5的命令行 1.4、用命令行进入新建文件夹package&#xff0c;使用windeployqt对生成的exe文件进行动…

Android Button修改背景颜色及实现科技感效果

目录 效果展示 实现科技感效果 修改Button背景 结语 效果展示 Android Button修改背景颜色及实现科技感效果效果如下&#xff1a; 实现科技感效果 操作方法如下&#xff1a; 想要创建一个富有科技感的按钮样式时&#xff0c;可以使用 Android 的 Shape Drawable 和 Sele…

阿里云发布通义千问2.0,模型参数达千亿级

10月31日&#xff0c;阿里云正式发布千亿级参数大模型通义千问2.0。在10个权威测评中&#xff0c;通义千问2.0综合性能超过GPT-3.5&#xff0c;正在加速追赶GPT-4。当天&#xff0c;通义千问APP在各大手机应用市场正式上线&#xff0c;所有人都可通过APP直接体验最新模型能力。…

精密数据工匠:探索 Netty ChannelHandler 的奥秘

通过上篇文章&#xff08;Netty入门 — Channel&#xff0c;把握 Netty 通信的命门&#xff09;&#xff0c;我们知道 Channel 是传输数据的通道&#xff0c;但是有了数据&#xff0c;也有数据通道&#xff0c;没有数据加工也是没有意义的&#xff0c;所以今天学习 Netty 的第四…

一种支持热插拔的服务端插件设计思路

定位 服务端插件是一个逻辑扩展平台,提供了一个快速托管逻辑的能力。 核心特点 高性能:相对于RPC调用,没有网络的损耗,性能足够强劲。 高可靠:基于线程隔离,保证互不影响,插件的资源占用或崩溃等问题不直接影响业务。 部署快:不需要发布审核流程, 插件本身逻辑简短,…

有一个 3*4 的矩阵,找出其中值最大的元素,及其行列号

1解题思路&#xff1a; 首先学会输入二维数组&#xff1b;然后知道如何比较求最大值&#xff1b;最后就是格式问题&#xff1b; 2代码&#xff1a; #include<stdio.h> int main() {int a[3][4];int i,j,max,row,line;for(i0;i<3;i){printf("请输入二维数组\n&…

【JAVA】类与对象的重点解析

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 文章目录 前言类与对象的关系JAVA源文件有关类的重要事项static关键字 前言 Java是一种面向对象编程语言&#xff0c;OOP是Java最重要的概念之一。学习OOP时&#xff0c;学生必须理解面向…

架构设计之大数据架构(Lambda架构、Kappa架构)

大数据架构 一. 大数据技术生态二. 大数据分层架构三. Lambda架构3.1 Lambda架构分解为三层3.2 优缺点3.3 实际案例 四. Kappa架构4.1 结构图4.2 优缺点4.3 实际案例 五. Lambda架构与Kappa架构对比 其它相关推荐&#xff1a; 系统架构之微服务架构 系统架构设计之微内核架构 鸿…

杂货铺 | 报错记录(持续更新)

文章目录 ⚠️python SyntaxError: Non-UTF-8 code starting with ‘\xb3‘ in file⚠️partially initialized module ‘‘ has no attribute ‘‘(most likely due to a circular import)⚠️AttributeError: ‘DataFrame‘ object has no attribute ‘append‘ ⚠️python S…

OpenCV官方教程中文版 —— 分水岭算法图像分割

OpenCV官方教程中文版 —— 分水岭算法图像分割 前言一、原理二、示例三、完整代码 前言 本节我们将要学习 • 使用分水岭算法基于掩模的图像分割 • 函数&#xff1a;cv2.watershed() 一、原理 任何一副灰度图像都可以被看成拓扑平面&#xff0c;灰度值高的区域可以被看成…

企业知识库知识分类太有必要了,是省时省力的关键!

企业知识库是存储、组织和共享企业内部知识的重要工具。在现代企业中&#xff0c;知识是一项宝贵的资产&#xff0c;对于提高企业的竞争力和创新能力至关重要。而通过企业知识库进行知识分类&#xff0c;可以将海量信息有序划分和组织&#xff0c;让企业员工能够快速定位、理解…

贪心算法学习------优势洗牌

目录 一&#xff0c;题目 二&#xff0c;题目接口 三&#xff0c;解题思路和代码 全部代码&#xff1a; 一&#xff0c;题目 给定两个数组nums1和nums2,nums1相对于nums2的优势可以用满足nums1[i]>nums2[i]的索引i的数目来描述。 返回nums1的任意排序&#xff0c;使其优…

标签推荐Top-N列表优化算法_朱小兵

2算法模型 2&#xff0e;1 Top-N推荐列表重排序算法

AIGC - Qwen大模型:Qwen-7B模型推理部署

硬件环境 作为AIGC方面的小白来说&#xff0c;我抱着非常天真的想法&#xff0c;想让它在我的工作笔记本上用i5的CPU去跑&#xff0c;至于为什么这么想&#xff0c;当然是因为我没有GPU&#xff0c;身边也没有其他的带显卡电脑 恰好&#xff0c;在腾讯云看到了GN7的显示优惠活…

Android裁剪图片之后无法加载的问题

适配Android11之后更改了图片保存目录&#xff0c;导致裁剪之后图片一直无法加载&#xff08;fileNotfound&#xff09; 最主要的问题在于保存裁剪文件的目录不能为私有目录&#xff0c;因为裁剪工具是系统工具&#xff0c;无法直接访问项目本身的私有目录。 解决办法&#x…

算法---缺失的第一个正数

题目 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。示例 1&#xff1a;输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 示例 2&#xff1a;输入&#xff1a;nums …

一文6个概念带你成功入门自动化测试

自动化测试有以下几个概念&#xff1a; 单元测试集成测试E2E 测试快照测试测试覆盖率TDD 以及 BDD 等 简述 项目开发过程中会有几个经历。 版本发布上线之前&#xff0c;会有好几个小时甚至是更长时间对应用进行测试&#xff0c;这个过程非常枯燥而痛苦代码的复杂度达到了一…

Linux 环境变量 二

目录 获取环境变量的后两种方法 环境变量具有全局属性 内建命令 和环境变量相关的命令 c语言访问地址 重新理解地址 地址空间 获取环境变量的后两种方法 main函数的第三个参数 &#xff1a;char* env[ ] 也是一个指针数组&#xff0c;我们可以把它的内容打印出来看看。 …

线上机器cpu负载200%告警排查

CPU告警排查思路&#xff0c;正常情况就是如下两种情况 执行任务的java线程本身存在bug&#xff0c;死循环或者操作本身耗cpu&#xff0c;导致cpu占用过高jvm发生频繁gc&#xff0c;导致cpu过高 查看耗时较高的进程 top命令&#xff0c;并按大写P以cpu利用率排序&#xff0c;确…

学习笔记3——JVM基础知识

学习笔记系列开头惯例发布一些寻亲消息 链接&#xff1a;https://baobeihuijia.com/bbhj/contents/3/196593.html JVM&#xff08;Write Once&#xff0c;Run Anywhere&#xff09; 以下是一些学习时有用到的资料&#xff0c;只学习了JVM的基础知识&#xff0c;对JVM整体进…