当前位置: 首页 > news >正文

API Key 生成和鉴权机制:从随机凭证生成到请求拦截校验

文章目录

  • API Key 生成和鉴权机制:从随机凭证生成到请求拦截校验
    • 一、API Key 生成规则
    • 二、过期时间处理
    • 三、数据库表结构
    • 四、生成接口
    • 五、前端生成与首次展示
    • 六、列表页脱敏展示
    • 七、请求鉴权流程
    • 八、用户身份切换
    • 九、删除与撤销
    • 十、安全实现要点
      • 1. API Key 只展示一次
      • 2. 脱敏只发生在展示层
      • 3. 不在日志中打印完整 Key
      • 4. 支持过期和撤销
      • 5. 可以扩展权限边界
    • 十一、完整调用链路
    • 十二、总结

API Key 生成和鉴权机制:从随机凭证生成到请求拦截校验

本文介绍一种数据库查表型 API Key 实现方式,核心流程包括:API Key 生成、过期时间计算、数据库存储、前端展示、脱敏展示、请求头携带、后端拦截器校验和用户身份切换。

用户点击生成 API Key ↓ 前端调用生成接口 ↓ 后端获取当前登录用户 ID ↓ 生成 ak- + 无连字符 UUID ↓ 计算过期时间 ↓ 保存完整 Key 到 api_key 表 ↓ 前端弹窗展示完整 API Key ↓ 关闭弹窗后,列表接口只返回脱敏 Key ↓ 外部系统通过 Authorization 请求头携带完整 Key ↓ 后端拦截器提取 Bearer Token ↓ 判断是否为 ak- 开头 ↓ 查询 api_key 表 ↓ 校验存在性、删除状态、过期状态 ↓ 切换到 API Key 所属用户身份 ↓ 写入请求上下文 ↓ 放行业务接口

一、API Key 生成规则

本方案中的 API Key 不是 JWT,也不是加密 Token,而是一个随机字符串,格式如下:

ak- + 32 位无连字符 UUID

示例:

ak-550e8400e29b41d4a716446655440000

后端生成逻辑可以简化为:

publicApiKeygenerateApiKey(LonguserId,Stringremark,IntegerexpireDays){ApiKeyentity=newApiKey();entity.setUserId(userId);entity.setRemark(remark);entity.setApiKey("ak-"+generateRandomUuidWithoutDash());if(expireDays!=null&&expireDays>0){entity.setExpiredAt(now().plusDays(expireDays));}save(entity);returnentity;}

其中核心代码是:

entity.setApiKey("ak-"+generateRandomUuidWithoutDash());

ak-用于标识这是 API Key 类型凭证,便于和普通登录 Token、JWT 或其他认证凭证区分。

二、过期时间处理

生成 API Key 时,可以传入有效天数expireDays

if(expireDays!=null&&expireDays>0){entity.setExpiredAt(now().plusDays(expireDays));}

规则如下:

expireDaysexpired_at含义
7当前时间 + 7 天7 天后过期
30当前时间 + 30 天30 天后过期
0null永不过期
nullnull永不过期

如果expired_at为空,则表示 API Key 永不过期;如果不为空,则后续鉴权时需要判断当前时间是否已经超过该时间。

三、数据库表结构

API Key 最终保存到数据库中,一个简化表结构如下:

CREATETABLEapi_key(idBIGINTPRIMARYKEYAUTO_INCREMENT,user_idBIGINTNOTNULL,api_keyVARCHAR(128)NOTNULL,remarkVARCHAR(255)DEFAULTNULL,expired_atDATETIMEDEFAULTNULL,create_timeDATETIMEDEFAULTCURRENT_TIMESTAMP,update_timeDATETIMEDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,is_deletedTINYINTNOTNULLDEFAULT0,UNIQUEKEYuk_api_key(api_key),KEYidx_user_id(user_id));

关键字段说明:

字段作用
user_idAPI Key 所属用户
api_key实际访问凭证
remarkKey 的备注说明
expired_at过期时间,空表示永不过期
is_deleted软删除标记
uk_api_key保证 API Key 唯一

这种设计的特点是,Key 本身不携带用户信息、权限信息和过期信息,所有状态都通过数据库查询获得。

四、生成接口

后端提供生成 API Key 的接口,简化逻辑如下:

publicApiResponse<ApiKey>generate(ApiKeyGenerateRequestrequest){LongcurrentUserId=getCurrentLoginUserId();ApiKeyapiKey=apiKeyService.generateApiKey(currentUserId,request.getRemark(),request.getExpireDays());returnApiResponse.success(apiKey);}

关键点:

  1. 生成 API Key 的用户必须是当前登录用户;
  2. 前端传入remarkexpireDays
  3. 后端根据当前用户 ID 生成 API Key 并落库;
  4. 生成后将完整 API Key 返回给前端展示。

五、前端生成与首次展示

前端请求方法可以封装为:

exportasyncfunctiongenerateApiKey(params:{remark?:string;expireDays?:number;}){returnrequest.post('/api-key/generate',params);}

页面调用逻辑可以简化为:

asyncfunctionhandleGenerate(){if(!form.remark){showError('请输入备注');return;}constdata=awaitgenerateApiKey(form);showSuccessModal({title:'生成成功',content:`请妥善保管您的 API Key,关闭后将无法再次查看全文:\n\n${data.apiKey}`,});refreshList();}

这里有一个关键设计:完整 API Key 只在生成成功时展示一次。

生成接口/api-key/generate返回的是ApiKeyEntity,其中包含完整的apiKey。前端拿到完整值后,通过Modal.success弹窗展示给用户,并提示用户妥善保存。

用户关闭弹窗后,再回到 API Key 列表页时,就只能看到脱敏后的 Key。

六、列表页脱敏展示

API Key 的脱敏展示只发生在返回列表时的 VO 转换阶段,也就是展示层处理,不影响数据库中的真实存储。

数据库中的api_key字段仍然保存完整 API Key,后续鉴权时也仍然使用完整 Key 进行查询。

后端列表接口/api-key/list返回的是ApiKeyVO,在实体转换为 VO 时,通过ApiKeyConvertor.maskApiKey()apiKey字段进行脱敏处理。

脱敏逻辑如下:

@Named("maskApiKey")defaultStringmaskApiKey(StringapiKey){if(apiKey==null||apiKey.length()<12){returnapiKey;}returnapiKey.substring(0,8)+"***"+apiKey.substring(apiKey.length()-4);}

脱敏规则是:

前 8 位 + "***" + 后 4 位

例如:

ak-7ebfc***b045

也就是说,列表接口拿到的apiKey本身就是脱敏后的值,而不是完整 API Key。

对应链路可以理解为:

api_key 表保存完整 Key ↓ /api-key/list 查询数据 ↓ ApiKeyEntity 转 ApiKeyVO ↓ MapStruct 调用 maskApiKey() ↓ 返回脱敏后的 apiKey ↓ 前端列表展示

这样可以保证列表页即使被打开,也不会直接暴露完整 API Key。

前端列表页使用 Ant Design Vue 的Table展示数据,并通过自定义单元格#bodyCell处理apiKey列的渲染。

apiKey列中,可以使用<code>标签配合 Tailwind 类展示脱敏后的 Key,使其更接近凭证样式:

<code class="..."> {{ record.apiKey }} </code>

如果前端拿到的是完整 Key,也可以通过同样的规则进行二次脱敏拼接:

apiKey.substring(0,8)+'***'+apiKey.substring(apiKey.length-4)

不过在当前实现中,后端列表接口已经返回脱敏值,因此前端主要负责样式渲染。

列表页中的时间字段也会在前端格式化展示:

dayjs(value).format('YYYY-MM-DD HH:mm:ss')

其中:

  • createTime展示为标准时间格式;
  • expiredAt如果为空,则显示为“永不过期”;
  • expiredAt如果不为空,则格式化为YYYY-MM-DD HH:mm:ss

这一设计把“存储”和“展示”分离开:

数据库:保存完整 API Key 生成弹窗:展示一次完整 API Key 列表接口:返回脱敏 API Key 列表页面:展示脱敏值和时间信息 鉴权逻辑:仍使用完整 API Key 查询数据库

七、请求鉴权流程

客户端调用接口时,需要在请求头中携带 API Key:

Authorization: Bearer ak-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

后端通过拦截器统一处理 API Key 鉴权逻辑:

publicbooleanpreHandle(HttpRequestrequest,HttpResponseresponse,Objecthandler){StringauthHeader=request.getHeader("Authorization");if(isBlank(authHeader)){returntrue;}Stringtoken=authHeader.replace("Bearer ","").trim();if(!token.startsWith("ak-")){returntrue;}ApiKeyapiKey=apiKeyService.getByApiKey(token);if(apiKey==null||apiKey.isDeleted()){thrownewUnauthorizedException("API Key 无效");}if(apiKey.getExpiredAt()!=null&&apiKey.getExpiredAt().isBefore(now())){thrownewUnauthorizedException("API Key 已过期");}switchToUser(apiKey.getUserId());requestContext.set("API_KEY_AUTH",true);requestContext.set("API_KEY_ID",apiKey.getId());returntrue;}

鉴权流程如下:

读取 Authorization 请求头 ↓ 提取 Bearer 后面的 Token ↓ 判断是否以 ak- 开头 ↓ 不是 API Key,则交给后续常规鉴权流程 ↓ 是 API Key,则查询数据库 ↓ 判断 Key 是否存在 ↓ 判断 Key 是否被删除 ↓ 判断 Key 是否过期 ↓ 校验通过后切换到所属用户身份 ↓ 写入当前请求上下文 ↓ 放行请求

需要注意的是,列表页展示的脱敏 Key 不能用于接口调用。外部系统调用接口时,必须使用生成时弹窗中展示过的完整 API Key。

八、用户身份切换

API Key 校验通过后,需要将当前请求临时绑定到 API Key 所属用户:

switchToUser(apiKey.getUserId());

这样后续业务逻辑就可以继续复用原有的用户上下文,例如:

  • 查询当前用户资源;
  • 保存当前用户数据;
  • 执行用户维度的接口逻辑;
  • 记录用户维度的操作日志。

需要注意的是,API Key 认证只是在当前请求上下文中临时切换用户身份,不等于创建真实登录会话。

九、删除与撤销

前端删除 API Key 的请求可以封装为:

exportasyncfunctiondeleteApiKey(id:number|string){returnrequest.delete(`/api-key/${id}`);}

后端可以通过软删除实现撤销:

apiKey.setDeleted(true);updateById(apiKey);

后续请求如果继续携带已删除的 API Key,拦截器会在校验阶段拦截:

if(apiKey==null||apiKey.isDeleted()){thrownewUnauthorizedException("API Key 无效");}

这样可以在不物理删除数据的情况下,实现 API Key 的失效和审计保留。

十、安全实现要点

1. API Key 只展示一次

生成成功后完整展示一次,后续管理页面只展示脱敏内容,例如:

ak-550e****0000

2. 脱敏只发生在展示层

脱敏展示不修改数据库中的真实 API Key,只在列表接口返回ApiKeyVO时处理。

也就是说:

数据库存储:完整 Key 列表返回:脱敏 Key 接口鉴权:完整 Key

这样既能保证安全展示,又不会影响后端通过完整 Key 查库鉴权。

3. 不在日志中打印完整 Key

避免如下日志:

log.warn("API Key {} 无效",apiKey);

建议改为脱敏输出:

log.warn("API Key {} 无效",maskApiKey(apiKey));

4. 支持过期和撤销

通过expired_at控制过期时间,通过is_deleted控制撤销状态。

5. 可以扩展权限边界

如果后续安全要求更高,可以继续扩展:

  • 绑定接口权限;
  • 区分只读和读写;
  • 限制来源 IP;
  • 增加调用频率限制;
  • 记录最近使用时间;
  • 记录 API Key 调用日志。

十一、完整调用链路

用户点击生成 API Key ↓ 前端调用生成接口 ↓ 后端获取当前登录用户 ID ↓ 生成 ak- + 无连字符 UUID ↓ 计算过期时间 ↓ 保存完整 Key 到 api_key 表 ↓ 前端弹窗展示完整 API Key ↓ 关闭弹窗后,列表接口只返回脱敏 Key ↓ 外部系统通过 Authorization 请求头携带完整 Key ↓ 后端拦截器提取 Bearer Token ↓ 判断是否为 ak- 开头 ↓ 查询 api_key 表 ↓ 校验存在性、删除状态、过期状态 ↓ 切换到 API Key 所属用户身份 ↓ 写入请求上下文 ↓ 放行业务接口

十二、总结

这是一种典型的数据库查表型 API Key 机制。

它的核心实现是:

生成阶段:ak- + 随机字符串,保存完整 Key 到数据库 展示阶段:生成时展示一次完整 Key,列表页只返回脱敏 Key 鉴权阶段:请求头携带完整 Key,后端查库校验

该方案的优点是实现简单、状态可控、撤销方便,并且通过“只展示一次全文 + 列表脱敏展示”的方式降低了 Key 泄露风险。

它适合用于第三方系统调用、自动化脚本、AI Agent、内部工具和轻量级服务集成等场景。

http://www.rkmt.cn/news/1491777.html

相关文章:

  • 旅游景点数据一键分析包:含动态地图、词云、TOP榜单与分词处理
  • 用树莓派4当主力开发机:低成本搭建Matter控制器(Chip-tool)与设备调试全流程
  • QLoRA微调BERT实战:4GB显存跑通NER任务
  • STM32F103驱动DS18B20温度传感器的Keil工程包(含单总线时序实现与调试配置)
  • 深耕技术,赋能增长 —— 为何企业 GEO 优化首选好客搜智搜 GEO 系统
  • PHP常量与枚举定义最佳实践
  • 模电课设别再头疼了!手把手教你用LM358和滑动变阻器搞定水位检测报警电路
  • 低代码平台架构演进:从 Schema 驱动到 AI 生成式 UI 的工程化方案
  • 从MobileNet到CoAtNet:聊聊那些年我们追过的轻量级网络设计思路
  • 保姆级教程:用Python手写A*算法,5分钟搞定扫地机器人最短路径规划
  • MuleSoft+LLM企业级AI编排:构建可审计、可治理、高韧性的智能工作流
  • 同一段 Prompt 跑 5 个大模型,输出差异让我重新审视模型选型
  • 现场五招验苗技巧,不用专业设备筛选优质鱼苗
  • 大厂笔试“潜规则”:性格测试、情商题怎么破?附真实题型拆解
  • 宁德市黄金回收本地靠谱店铺指南+白银回收+铂金回收+彩金回推荐收门店 及地联系方式址推荐 - 盛世金银回收
  • 攀枝花市黄金回收本地靠谱店铺指南+白银回收+铂金回收+彩金回推荐收门店 及地联系方式址推荐 - 盛世金银回收
  • 日月不失其体,故蔽而复明;江汉不失其源,故穷而复通
  • Java+Vue漫画阅读系统源码包:含部署教程、接口文档、数据库脚本与答辩PPT
  • FPGA开发用SPI模式0主从通信Verilog工程,含ModelSim可运行仿真环境
  • Arduino 433MHz无线收发实战包:VirtualWire源码+DHT11传输示例+全文档
  • Unlock Music音乐解锁工具:3分钟快速解密所有加密音乐格式
  • 平凉市黄金回收本地靠谱店铺指南+白银回收+铂金回收+彩金回推荐收门店 及地联系方式址推荐 - 盛世金银回收
  • matchexpression和matchlabels的区别
  • 智能容量规划:基于时序预测的弹性伸缩实践,从经验估算到数据驱动
  • 金华市黄金回收本地靠谱店铺指南+白银回收+铂金回收+彩金回推荐收门店 及地联系方式址推荐 - 盛世金银回收
  • 浏览器用户画像分析 - 大屏数据接入
  • 剪辑问题不知道问谁怎么办?5款工具实测对比
  • 2025-2026年上海屋宁遮阳设备有限公司电话查询:选购户外遮阳产品前需了解的事项 - 品牌推荐
  • PHP写的电视直播系统,网页和手机都能推流看直播
  • 2026夏季工作服衬衫,清凉透气怎么选?