当前位置: 首页 > 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.jsqmd.com/news/980051/

相关文章:

  • 橙子设计:二手房翻新/室内设计/装修设计/新房装修/精装房改造公司,深耕重庆主城区等地区,靠谱家装之选 - 十大品牌榜
  • 嵌入式Linux下CANopen移植避坑指南:从定时器精度到SDO通信的实战调优
  • SPD矩阵与EEG分类的几何特性及Transformer应用
  • 旅游景点数据一键分析包:含动态地图、词云、TOP榜单与分词处理
  • BentoML vs FastAPI:模型服务化中的角色定位与协同实践
  • Pandas多维聚合:用MultiIndex构建业务语义数据立方体
  • DDPG到TD3:算法进化史与调参避坑指南(基于Gymnasium环境)
  • 《PE不饱和聚酯漆的特点与适用范围详解》
  • VCS仿真时FSDB文件生成失败?盘点$fsdbDumpvars的那些坑与正确姿势
  • 视觉语言模型在机器人导航中的实时优化与边缘部署
  • STM32F103驱动DS18B20温度传感器的Keil工程包(含单总线时序实现与调试配置)
  • QLoRA微调BERT实战:4GB显存跑通NER任务
  • SpringBoot项目快速接入讯飞语音听写,支持实时麦克风与WAV音频转中文文本
  • 蓝桥杯嵌入式省赛复盘:第九届赛题里那些新手容易踩的EEPROM和长短按按键的坑
  • 2026年健康照明品牌深度横评:谁才是真正专业的健康照明引领者? - 资讯焦点
  • PHP常量与枚举定义最佳实践
  • 告别混乱!用APDL批处理模式高效管理你的ANSYS仿真工作流
  • 计算机毕业设计之基于Hadoop1688平台数据的分析与可视化
  • 深耕技术,赋能增长 —— 为何企业 GEO 优化首选好客搜智搜 GEO 系统
  • C++控制台版宾馆客房管理系统源码(含完整报告与编译说明)
  • RK3588 Android12开发:如何高效管理自定义分支并与官方SDK同步(避坑指南)
  • 模电课设别再头疼了!手把手教你用LM358和滑动变阻器搞定水位检测报警电路
  • 【LeetCode刷题日记】78.子集
  • 树莓派4B不只是控制器:一机搞定Matter设备固件编译与调试全流程
  • 从MobileNet到CoAtNet:聊聊那些年我们追过的轻量级网络设计思路
  • 告别C盘爆满!手把手教你将Qt5.12.6完整安装到D盘(Win10环境,含环境变量检查)
  • 2026降AIGC软件实测:10款软件对比,学术合规技巧盘点
  • 低代码平台架构演进:从 Schema 驱动到 AI 生成式 UI 的工程化方案
  • 从‘信息检索’视角拆解Transformer Attention:你的Query如何找到最相关的Key与Value?
  • MuleSoft+LLM企业级AI编排:构建可审计、可治理、高韧性的智能工作流