短链服务需求文档
短链服务需求文档
1. 背景
当前系统需要新增短链服务,将较长的业务链接转换成短链接,便于短信、站内信、邮件、二维码、第三方系统回调等场景使用。
示例:
- 原始链接:
https://juejin.cn/post/7444801892247683110?searchId=2026052014344763402A9D063F9D5207AE - 期望短链:
https://s.tudicloud.com/ESASVDSX
注意:短链域名必须是系统可控制、可解析并可路由到本服务的域名。若要生成 https://juejin.cn/ESASVDSX,必须拥有 juejin.cn 的路由控制权或对方提供转发能力;否则系统只能生成自有域名下的短链,例如 https://s.tudicloud.com/ESASVDSX。
2. 开源项目参考
本需求参考以下开源短链/链接管理项目的能力边界,并按 Tudicloud 医疗系统的安全、审计和数据范围要求做收敛。
| 项目 | 参考地址 | 可借鉴能力 | 本系统一期取舍 |
|---|---|---|---|
| Shlink | GitHub、官网、Features、QR Code Docs | 自托管、多域名、访问统计、地域、标签、访问期限/次数限制、REST API、二维码参数 | 借鉴多域名、标签、地域统计、二维码参数、API-first;暂不做动态跳转和邮件追踪 |
| Kutt | GitHub | 自托管、自定义域名、自定义短码、密码、描述、过期时间、私有统计、REST API、后台用户管理 | 借鉴密码访问、过期时间、自定义短码、统计和后台管理;注册开放能力不纳入一期 |
| YOURLS | GitHub、API Docs、Plugins | 自托管、API、短链生成、展开长链、链接统计、插件扩展、数据自主 | 借鉴 API 动作边界和统计能力;插件市场不纳入一期 |
| Dub | GitHub、官网 | 链接管理、分析统计、二维码、文件夹/团队协作、归因和转化分析 | 借鉴链接管理和二维码体验;归因、联盟营销、A/B 和深链作为二期以后能力 |
一期结论:
- 必须做:短码生成、后台管理、开放 API、分组标签、二维码、密码/私密访问、访问统计、地域地图、安全白名单。
- 暂缓做:动态规则跳转、营销归因、A/B 测试、多团队商业化协作、插件市场、第三方导入。
- 医疗系统额外要求:访问日志脱敏、密码/token 哈希保存、目标 URL 白名单、内网地址拦截、操作审计。
3. 建设目标
- 提供统一短链生成能力:输入长链接,返回短链接。
- 提供稳定跳转能力:访问短码时快速 301/302 跳转到原始链接。
- 提供后台管理能力:查询、创建、编辑、启停、删除短链。
- 提供组织管理能力:短链分组、标签、批量归类、按业务来源聚合。
- 提供二维码能力:生成、预览、下载、记录二维码生成参数。
- 提供访问保护能力:公开短链、私密短链、密码访问、密码错误限制。
- 提供统计分析能力:累计访问量、独立访客、最近访问时间、按天统计、地域统计和地图分布。
- 提供安全治理能力:域名白名单、协议限制、恶意链接拦截、频率限制、防枚举。
- 支持开放 API:给内部模块和第三方系统调用,便于短信、消息中心、工单等业务集成。
4. 一期范围
4.1 短链生成
后台和开放 API 均可创建短链。
创建参数:
originUrl:原始长链接,必填,最大长度建议 2048 或 4096。domain:短链域名,可选,默认系统配置域名。code:自定义短码,可选;为空时系统自动生成。title:短链标题,可选。description:描述,可选。expireTime:过期时间,可选;为空表示长期有效。status:状态,默认启用。remark:备注,可选。bizType:业务类型,可选,例如MESSAGE、TICKET、MANUAL。bizId:业务 ID,可选,用于关联来源业务。groupId:分组 ID,可选,默认归入“未分组”。tagIds:标签 ID 列表,可选,便于活动、渠道、业务线检索。accessType:访问类型,默认公开访问;可选私密或密码访问。accessPassword:访问密码,当访问类型为密码访问时必填。qrEnabled:是否生成默认二维码,可选。
生成规则:
- 自动短码默认使用 Base62 字符集:
0-9a-zA-Z。 - 默认长度建议 7 到 8 位,可通过配置调整。
- 短码需在同一短链域名下唯一。
- 支持自定义短码,自定义短码只允许字母、数字、短横线、下划线,长度建议 4 到 32 位。
- 禁止占用系统路径和保留字,例如
admin、api、health、login、swagger-ui、favicon.ico。 - 同一调用方在相同
originUrl + domain + bizType + bizId下可选择复用已有短链,避免重复生成。
4.2 短链跳转
访问规则:
- 请求
GET /{code} 或GET /s/{code},系统解析短码。 - 短码不存在、已删除、已停用、已过期时返回错误页或 404。
- 命中后记录访问日志,再跳转到
originUrl。 - 默认使用 302 临时跳转;后台可配置是否允许 301 永久跳转。
跳转要求:
- 跳转接口必须低延迟,优先从 Redis 缓存读取短码映射。
- 缓存未命中时查询数据库,并回填缓存。
- 停用、删除、过期短链需要及时清理或失效缓存。
- 访问日志写入不能阻塞跳转主流程,建议异步落库或批量写入。
4.3 后台管理
后台提供短链管理页面和接口:
- 分页查询:支持按短码、原始链接、域名、标题、业务类型、状态、创建时间、过期时间筛选。
- 创建短链:支持自动短码和自定义短码。
- 编辑短链:支持修改原始链接、标题、描述、过期时间、状态、备注。
- 启用/停用:停用后访问短链不再跳转。
- 删除:建议逻辑删除,保留统计和审计数据。
- 详情:展示基础信息、统计摘要和最近访问记录。
- 分组管理:新增、编辑、启停、删除分组,支持设置默认分组和排序。
- 标签管理:新增、编辑、删除标签,支持颜色、排序和使用次数统计。
- 二维码管理:短链详情中预览二维码,支持 PNG/SVG 下载和参数记录。
- 访问保护:创建和编辑时配置公开、私密、密码访问策略。
- 地域分析:统计页展示省份/城市排行和中国地图分布。
权限建议:
system:short-link:viewsystem:short-link:createsystem:short-link:updatesystem:short-link:statussystem:short-link:deletesystem:short-link:statssystem:short-link:groupsystem:short-link:tagsystem:short-link:qrcode
4.4 开放 API
面向内部模块和可信第三方提供 API。
接口建议:
POST /short-link/create:创建短链。POST /short-link/batch-create:批量创建短链。GET /short-link/detail:按短链 ID 或短码查询详情。POST /short-link/disable:停用短链。GET /short-link/stats:查询统计摘要。POST /short-link/qrcode/create:生成二维码。GET /short-link/qrcode/download:下载二维码。
开放 API 要求:
- 复用现有 openapi 鉴权和限流能力。
- 写接口加幂等控制,支持
requestId或业务唯一键。 - 返回统一
BaseResult响应结构。 - 调用方维度限流,防止批量刷短链。
4.5 统计分析
一期统计以实用为主,不做复杂营销归因。
统计指标:
- 总访问次数
visitCount。 - 独立访客数
uvCount,可基于 IP + User-Agent 哈希粗略计算。 - 今日访问次数。
- 最近访问时间。
- 按天访问趋势。
- Referer 来源。
- 设备类型:PC、Mobile、Tablet、Bot。
- 浏览器和操作系统。
- 国家、省份、城市、经纬度或地图编码,用于地域统计和地图分布。
日志采集字段:
- 短链 ID。
- 短码。
- 短链域名。
- 访问时间。
- IP。
- User-Agent。
- Referer。
- 访问结果:成功、停用、过期、不存在、风控拦截。
- 请求 ID 或 traceId。
- 国家、省份、城市、运营商、经纬度或地图编码。
4.6 安全治理
安全是短链服务的核心要求,一期必须包含。
原始链接校验:
- 只允许
http 和https,默认仅允许https。 - 禁止
javascript:、data:、file:、ftp:等协议。 - 禁止空 host、非法域名、内网地址、回环地址、本机地址、链路本地地址。
- 支持原始链接域名白名单,建议复用或扩展现有消息中心外链域名白名单能力。
- 可配置是否允许任意公网域名;生产建议关闭。
短码安全:
- 短码随机生成时避免递增 ID 直接暴露,降低枚举风险。
- 跳转接口需要限流,按 IP、短码、调用方维度控制。
- 对不存在短码的频繁访问进行拦截或黑名单策略。
- 自定义短码需要校验保留字和敏感词。
跳转安全:
- 跳转前重新确认短链状态和过期时间。
- 短链编辑后必须刷新缓存。
- 支持管理员一键停用风险短链。
- 所有创建、编辑、停用、删除动作进入操作日志。
4.7 分组和标签
分组和标签纳入一期,用于提高短链管理效率。
分组要求:
- 每条短链只能归属一个分组。
- 系统内置“默认分组/未分组”,不可删除。
- 分组支持名称、编码、状态、排序、描述。
- 停用分组后不可再选择,但已归属短链仍保留历史归属。
- 删除分组前需校验是否存在短链;存在短链时不允许删除或需要先迁移到其他分组。
标签要求:
- 每条短链可绑定多个标签。
- 标签支持名称、颜色、状态、排序、描述。
- 标签名称在同一租户/系统内唯一。
- 删除标签后解除短链绑定关系,但不删除短链。
- 列表页支持按分组和标签组合筛选。
4.8 二维码生成和下载
二维码能力纳入一期,用于线下扫码、短信补充、邮件落地页等场景。
二维码要求:
- 支持为短链生成二维码,二维码内容为完整短链 URL。
- 支持前端即时预览,后端提供下载接口。
- 下载格式一期支持 PNG,设计上预留 SVG。
- 支持尺寸、边距、纠错级别、前景色、背景色。
- 支持带 Logo 的二维码作为二期增强,若一期实现需控制 Logo 大小和纠错级别。
- 二维码生成参数需要记录,便于重复下载得到一致结果。
- 短链停用、删除、过期后,二维码仍可下载,但扫码访问不能跳转。
4.9 密码访问和私密短链
访问保护纳入一期,用于控制敏感链接传播范围。
访问类型:
- 公开访问:访问短链后直接跳转。
- 私密短链:仅允许登录用户或可信内部请求访问,不对公网匿名访问开放。
- 密码访问:访问短链时先进入密码校验页,密码正确后再跳转。
密码要求:
- 密码不明文保存,后端保存加盐哈希。
- 后台创建和重置密码时只允许写入,不允许回显原密码。
- 密码错误需要按 IP + 短链维度限流。
- 密码校验通过后可写入短期访问凭证,避免同一访问者短时间内反复输入。
- 私密和密码短链访问日志要记录校验结果,但不能记录明文密码。
4.10 地域统计和地图分布
地域统计纳入一期,用于分析短链传播范围和异常访问来源。
地域要求:
- 访问日志写入时解析访问 IP 所属国家、省份、城市。
- 统计页支持省份排行、城市排行、中国地图分布。
- 对未知、内网、本机、解析失败 IP 归入“未知”。
- 后台展示 IP 时支持脱敏,地图只展示聚合数据。
- 地域解析依赖本地离线库或可替换 Provider,不能让跳转主流程强依赖外部网络。
5. 二期增强
二期可按业务价值逐步加入:
- 自定义短链域名管理。
- 访问次数上限,达到上限后自动失效。
- A/B 跳转、多目标链接、按设备/地区跳转。
- UTM 参数模板。
- Webhook:短链访问后推送事件。
- 团队空间、数据权限、创建人隔离。
- 高级反滥用:恶意域名库、钓鱼链接检测、Bot 识别。
6. 推荐模块设计
建议将短链服务放在 tudicloud-module-system 中,原因:
- 短链是平台基础能力,不属于医学编码业务。
- 需要复用系统模块已有的权限、用户、操作日志、OpenAPI、Redis、MyBatis 能力。
- 可供消息中心、工单、文件分享等多个业务模块复用。
建议包结构:
com.tudicloud.module.system.controller.admin.shortlink
com.tudicloud.module.system.controller.openapi.shortlink
com.tudicloud.module.system.controller.publicapi.shortlink
com.tudicloud.module.system.service.admin.shortlink
com.tudicloud.module.system.service.api.shortlink
com.tudicloud.module.system.service.publicapi.shortlink
com.tudicloud.module.system.dao.domain
com.tudicloud.module.system.dao.mapper
com.tudicloud.module.system.dto.req.shortlink
com.tudicloud.module.system.dto.resp.shortlink说明:
admin:后台管理接口。openapi:给可信系统调用的创建、管理、查询接口。publicapi:公开跳转接口,不要求登录,但必须有风控。
7. 数据模型草案
最终数据库结构以 short-link-service-schema.sql 为准,SQL 评审稿见 short-link-service-sql-review.md。需求阶段只确认表边界和关键能力。
设计约定:
- 一期数据表统一放入
tudicloud-module-system,表名使用system_short_link_*。 - 每张表都要有独立 Domain、Mapper、Service、ServiceImpl。
- 密码不放在短链主表,独立保存到密码配置表,并且只保存哈希。
- 访问 token 不明文入库,只保存 token 哈希。
- 访问日志不保存患者姓名、证件号、手机号等敏感信息。
| 表 | 一期用途 | 关键字段 |
|---|---|---|
system_short_link_domain | 短链域名配置 | domain_url、path_prefix、is_default、status |
system_short_link_target_whitelist | 目标 URL 白名单 | rule_type、rule_value、allow_subdomain、biz_type |
system_short_link_group | 分组管理 | group_code、group_name、parent_id、sort_no、link_count |
system_short_link_tag | 标签管理 | tag_name、tag_color、sort_no、use_count |
system_short_link | 短链主表 | domain_id、group_id、short_code、short_url、origin_url、origin_url_hash、access_type、status、expire_time、visit_count、uv_count |
system_short_link_tag_rel | 短链与标签关系 | short_link_id、tag_id |
system_short_link_qrcode | 二维码配置与下载统计 | short_link_id、size_px、error_correction_level、qrcode_url、download_count |
system_short_link_password | 密码访问配置 | short_link_id、password_hash、password_algo、fail_limit、credential_ttl_minutes |
system_short_link_access_token | 密码访问通过后的短期凭证 | short_link_id、token_hash、visitor_hash、expire_time、usage_count |
system_short_link_visit_log | 访问明细日志 | short_link_id、short_code、access_time、visitor_hash、ip_hash、ip_masked、province_code、city_code、access_result |
system_short_link_daily_stats | 每日趋势统计 | short_link_id、stat_date、pv_count、uv_count、success_count、fail_count |
system_short_link_region_stats | 地域地图和排行 | short_link_id、stat_date、country/province/city、pv_count、uv_count |
system_short_link_operation_log | 操作审计 | operation_type、target_type、target_id、before_data、after_data、operation_time |
system_short_link_api_idempotency | OpenAPI 幂等 | idempotency_key、request_hash、status、expire_time |
关键约束:
system_short_link 使用(domain_id, short_code)唯一索引,软删除后不复用短码。short_code必须大小写敏感。origin_url 不直接建索引,使用origin_url_hash检索和复用。system_short_link_daily_stats 和system_short_link_region_stats使用唯一键配合 upsert。- 访问日志、统计表、操作日志不建物理外键,降低高频写入风险。
8. 接口草案
8.1 创建短链
POST /short-link/create
请求:
{
"originUrl": "https://juejin.cn/post/7444801892247683110?searchId=2026052014344763402A9D063F9D5207AE",
"domain": "https://s.tudicloud.com",
"code": "",
"title": "掘金文章",
"bizType": "MANUAL",
"bizId": "",
"expireTime": null,
"reuse": true,
"requestId": "REQ-20260520-0001"
}响应:
{
"id": "短链ID",
"domain": "https://s.tudicloud.com",
"code": "ESASVDSX",
"shortUrl": "https://s.tudicloud.com/ESASVDSX",
"originUrl": "https://juejin.cn/post/7444801892247683110?searchId=2026052014344763402A9D063F9D5207AE",
"expireTime": null,
"status": 1
}8.2 短链跳转
GET /{code}
处理结果:
- 成功:302 跳转到
originUrl。 - 短码不存在:404。
- 短链停用:410 或系统错误页。
- 短链过期:410 或系统错误页。
- 命中安全策略:403。
8.3 分页查询
GET /system/short-link/page
查询条件:
codeoriginUrldomainbizTypestatuscreateTimeStartcreateTimeEndexpireTimeStartexpireTimeEnd
8.4 统计摘要
GET /system/short-link/stats?id=xxx
响应字段:
visitCountuvCounttodayVisitCountlastVisitTimedailyTrendrefererTopdeviceTop
9. 缓存设计
Redis Key 建议:
system:short-link:code:{domain}:{code}:短码映射缓存。system:short-link:missing:{domain}:{code}:不存在短码短期缓存,防穿透。system:short-link:rate:ip:{ip}:跳转 IP 限流。system:short-link:rate:create:{caller}:创建接口调用方限流。
缓存策略:
- 启用短链缓存到 Redis,TTL 不超过短链过期时间。
- 长期有效短链可设置较长 TTL,例如 1 天,并支持主动刷新。
- 不存在短码缓存 1 到 5 分钟,防止恶意扫短码打穿数据库。
- 短链编辑、停用、删除后删除对应缓存。
10. 异常与错误码
建议新增错误码:
- 短链不存在。
- 短链已停用。
- 短链已过期。
- 原始链接格式非法。
- 原始链接域名未通过白名单。
- 短码已存在。
- 短码包含非法字符。
- 短码为系统保留字。
- 创建频率过高。
- 跳转频率过高。
11. 非功能需求
性能:
- 短链跳转接口 P95 延迟目标小于 50ms,缓存命中场景。
- 创建接口 P95 延迟目标小于 300ms。
- 访问日志异步写入,避免影响跳转。
可用性:
- Redis 故障时可降级查询数据库。
- 日志写入失败不影响跳转,但需要记录错误日志和监控。
- 短码生成冲突时自动重试,重试次数可配置。
可观测性:
- 记录短链创建、编辑、停用、删除操作日志。
- 记录跳转成功率、解析失败数、风控拦截数。
- 对异常短链访问量突增提供监控指标。
合规:
- 访问日志中的 IP、User-Agent 属于敏感数据,保留周期需要可配置。
- 后台展示 IP 时可支持脱敏。
- 支持按短链删除或归档访问日志。
12. 验收标准
- 输入合法长链接后,系统能返回唯一可访问短链。
- 访问短链能跳转到原始链接,并记录访问日志。
- 自定义短码冲突时创建失败并返回明确错误。
- 停用、删除、过期短链不能继续跳转。
- 非
http/https协议、内网地址、未通过白名单的链接不能创建。 - 后台可分页查询、创建、编辑、启停、删除短链。
- 后台可查看短链访问量、独立访客、最近访问时间和按天趋势。
- 短链缓存命中、缓存失效、数据库兜底路径均通过测试。
- 开放 API 支持幂等和限流。
- 操作日志、错误日志、关键监控指标完整。
13. 实施优先级
一期建议按以下顺序实施:
- 数据表和实体、Mapper。
- 短码生成器、URL 校验器、保留字配置。
- 后台创建、查询、编辑、启停、删除接口。
- 公开跳转接口和 Redis 缓存。
- 访问日志异步写入和基础统计。
- OpenAPI 创建和查询接口。
- 权限菜单、接口文档、单元测试和集成测试。