外观
分享模式篇
目标:让集成方编排两条分享路径——面向已知身份接收方的站内分享(ShareGrant),以及面向不特定访问方的公开链接(ShareLink),理解各自的权限预设、token 契约、公开下载流,并规避常见坑。
不在本篇范围:分享按钮 UI 实现(集成方业务 UI 层,不在 ATKONBASE 对外能力范围);ACL 权限位与继承(见 ACL 与继承模式篇);资源生命周期(TRASHED 状态对分享的影响见 生命周期模式篇);错误码完整码表(见错误码参考)。
本篇覆盖三个对外面:V1 ShareGrant 端点(强身份,站内)、V1 ShareLink 端点(链接管理)、公开匿名下载端点 /public/s/{tenantCode}/{token}/...(无需登录的消费侧)。
关键事实
- 两条路径互不依赖:ShareGrant 授予指定 grantee,ShareLink 签发可分发的不透明 token;两者可以同时并用于同一资源。
- ShareLink 的
token是不透明字符串——不应尝试解析、拆分或在 URL 之外位置存储。 - 公开链接读侧要求 DOWNLOAD 位授予:
permissionBits未含2(DOWNLOAD)的 ShareLink,访问/public/s/.../meta或/download统一返回不可用响应——这是设计约束。集成方按需选择仅 READ(仅元数据可达,字节下载受限)或 READ + DOWNLOAD(完整公开下载)。 - ShareGrant 采用预设白名单:权限只能在
VIEW(READ + DOWNLOAD)或EDIT(READ + DOWNLOAD + WRITE)中选一,不接受裸位掩码。 - 站内分享的 grantor 始终是调用方代表的用户(由身份上下文解析),不可指定。
tenantCode是租户对外识别码(全局唯一短字符串),token在租户作用域内唯一;两者共同定位到一条 share_link 记录。- CONTAINER 类型的 ShareLink 支持目录浏览(
/list)和按path参数逐层下载;DOCUMENT / VERSION 类型不支持浏览,/list返回174001 SHARE_LINK_UNAVAILABLE。
一、站内分享(ShareGrant)
ShareGrant 授权给 ATKONBASE 内部已知的用户 / 角色 / 部门,grantor 推拉消息由集成方业务层负责(平台不发通知)。
创建或覆盖更新(POST /v1/share-grants/save)
同一 (resourceType, resourceId, grantee) 已存在活跃 grant 时语义为覆盖更新(不会新增重复条目)。
bash
curl -X POST 'https://api.atkonbase.example.com/v1/share-grants/save' \
-H 'Authorization: Bearer ${accessToken}' \
-H 'X-Atk-User-Token: ${userToken}' \
-H 'Content-Type: application/json' \
-d '{
"resourceType": "DOCUMENT",
"resourceId": "${docId}",
"grantee": {
"granteeType": "USER",
"granteeId": "${targetUserId}"
},
"permissionPreset": "VIEW",
"expiresAt": "2026-12-31T23:59:59.000+08:00",
"message": "请查看这份合同草稿"
}'resourceType取值DOCUMENT/CONTAINER。permissionPreset取值VIEW(等价 READ + DOWNLOAD)或EDIT(READ + DOWNLOAD + WRITE)。granteeType取值USER/ROLE/DEPARTMENT;granteeId是 ATKONBASE 内部稳定 ID(见 认证与身份双通道模式篇 §granteeId 解析)。expiresAt=null表示永不过期;不得晚于平台允许的最大 TTL(超出返code=1)。
期望响应(关键字段)
json
{
"code": 0,
"data": {
"shareGrantId": "SG1000001",
"resourceType": "DOCUMENT",
"resourceId": "${docId}",
"grantorId": "${currentUserId}",
"granteeType": "USER",
"granteeId": "${targetUserId}",
"permissionPreset": "VIEW",
"message": "请查看这份合同草稿",
"expiresAt": "2026-12-31T23:59:59.000+08:00",
"status": "ACTIVE",
"createTime": "2026-05-28T10:00:00.000+08:00"
}
}status取值ACTIVE/EXPIRED/REVOKED。
更新(POST /v1/share-grants/update)
仅允许改 permissionPreset / expiresAt / message:
bash
curl -X POST 'https://api.atkonbase.example.com/v1/share-grants/update' \
-H 'Authorization: Bearer ${accessToken}' \
-H 'X-Atk-User-Token: ${userToken}' \
-H 'Content-Type: application/json' \
-d '{
"shareGrantId": "${shareGrantId}",
"permissionPreset": "EDIT",
"expiresAt": null
}'撤销(GET /v1/share-grants/delete?shareGrantId=...)
仅创建者本人可撤销;grantee 无权撤销对自己的分享。
bash
curl -X GET 'https://api.atkonbase.example.com/v1/share-grants/delete?shareGrantId=${shareGrantId}' \
-H 'Authorization: Bearer ${accessToken}' \
-H 'X-Atk-User-Token: ${userToken}'查询分享列表
| 端点 | 含义 |
|---|---|
POST /v1/share-grants/getOutgoingPage | 当前用户分享出去的列表 |
POST /v1/share-grants/getIncomingPage | 分享给当前用户的列表 |
GET /v1/share-grants/{shareGrantId} | 单条详情(grantor 或 grantee 均可查) |
bash
curl -X POST 'https://api.atkonbase.example.com/v1/share-grants/getOutgoingPage' \
-H 'Authorization: Bearer ${accessToken}' \
-H 'X-Atk-User-Token: ${userToken}' \
-H 'Content-Type: application/json' \
-d '{ "pageSize": 20, "pageNumber": 1 }'二、公开链接(ShareLink)
ShareLink 生成一个不透明 token,集成方把 url 字段(完整可分发 URL)暴露给用户;访问者无需登录。
创建 ShareLink(POST /v1/share-links/save)
bash
curl -X POST 'https://api.atkonbase.example.com/v1/share-links/save' \
-H 'Authorization: Bearer ${accessToken}' \
-H 'Content-Type: application/json' \
-d '{
"resourceType": "DOCUMENT",
"resourceId": "${docId}",
"permissionBits": 3,
"ttlSeconds": 604800,
"password": "abc123",
"maxAccessCount": 100
}'resourceType取值DOCUMENT/VERSION/CONTAINER。permissionBits:1=READ(仅元数据可达)、2=DOWNLOAD(仅字节下载,不含元数据)、3=READ+DOWNLOAD(完整公开下载)。⚠️ 不含 DOWNLOAD 位时,访问/download返回174001 SHARE_LINK_UNAVAILABLE,这是约束设计——不是服务端错误。ttlSeconds=null表示链接永不过期。password可选;设置后访问侧需先调/verify端点验证密码(见 §三)。maxAccessCount可选;访问次数超限后链接自动失效。- 所需 scope:
client:storage:share-link:create。
期望响应(关键字段)
json
{
"code": 0,
"data": {
"shareLinkId": "SL1000001",
"token": "abc1def2ghi3",
"url": "https://api.atkonbase.example.com/public/s/${tenantCode}/abc1def2ghi3",
"resourceType": "DOCUMENT",
"resourceId": "${docId}",
"permissionBits": 3,
"expiresAt": "2026-06-04T10:00:00.000+08:00",
"maxAccessCount": 100,
"remainingCount": 100,
"requiresPassword": true,
"createTime": "2026-05-28T10:00:00.000+08:00"
}
}token—— 不透明字符串,不可解析内部结构,不应在 URL 之外位置存储或转发。url—— 完整可分发 URL;集成方直接把此字段的值暴露给用户,不要自行拼接路径。remainingCount—— 剩余可访问次数;未设置maxAccessCount时为null。requiresPassword—— 是否需要验证密码(访问侧参考此字段决定是否展示密码输入框)。
查询与撤销
bash
# 分页查我的 ShareLink
curl -X POST 'https://api.atkonbase.example.com/v1/share-links/getPage' \
-H 'Authorization: Bearer ${accessToken}' \
-H 'Content-Type: application/json' \
-d '{ "pageSize": 20, "pageNumber": 1 }'
# 撤销
curl -X GET 'https://api.atkonbase.example.com/v1/share-links/delete?shareLinkId=${shareLinkId}' \
-H 'Authorization: Bearer ${accessToken}'
# 详情
curl -X GET 'https://api.atkonbase.example.com/v1/share-links/${shareLinkId}' \
-H 'Authorization: Bearer ${accessToken}'撤销后 token 立即失效;访问侧返回 174001 SHARE_LINK_UNAVAILABLE。
三、公开匿名下载流(/public/s/{tenantCode}/{token}/...)
公开端点无需 Authorization header,适合嵌入浏览器直接访问或 iframe 渲染。
获取元信息
bash
curl -X GET 'https://api.atkonbase.example.com/public/s/${tenantCode}/${token}'返回 PublicShareMetaDTO,包含资源类型、标题、文件名、权限位、是否需要密码、剩余次数等。
验证密码(有密码的链接)
bash
curl -X POST 'https://api.atkonbase.example.com/public/s/${tenantCode}/${token}/verify' \
-H 'Content-Type: application/json' \
-d '{ "password": "abc123" }'验证通过返回 code=0;密码错误返回 174010 PASSWORD_INVALID;链接未设密码却传了密码返回 174011 PASSWORD_NOT_REQUIRED。消费侧应先检查 ShareLinkResultDTO.requiresPassword 字段,仅在 requiresPassword=true 时展示密码输入框并调 /verify。
浏览容器(仅 CONTAINER 类型)
bash
curl -X GET 'https://api.atkonbase.example.com/public/s/${tenantCode}/${token}/list?path=${subPath}&page=1&size=20'path可选,指向容器下某一层子容器(按业务命名路径,如folder-a/sub-b)。- DOCUMENT / VERSION 类型的 ShareLink 调用
/list一律返回174001 SHARE_LINK_UNAVAILABLE。
下载
bash
curl -X GET 'https://api.atkonbase.example.com/public/s/${tenantCode}/${token}/download?path=${docPath}'- DOCUMENT / VERSION 类型忽略
path(直接下载该资源)。 - CONTAINER 类型必须传
path指向子树内某个文档;path无效(不在子树内 / 对应资源已不存在)返回174014 SHARE_LINK_PATH_INVALID,建议先调/list获取合法路径再下载。 - 链接不可用统一返回
174001 SHARE_LINK_UNAVAILABLE(不区分具体原因以抗探测)。下载失败时,携带响应中的rid/X-Request-Id联系 ATKONBASE 支持团队。
⚠️ 公开链接不是客户端签名 URL(非 S3 风格预签名 URL)——集成方不需要也不应该在客户端计算任何签名。
url字段即完整可用 URL,直接使用即可。
四、ShareGrant 与 ACL 的关系
ShareGrant 是叠加授权,不是 ACL 替代品:
- ShareGrant 授予的
VIEW/EDIT预设是叠加在资源现有 ACL 之上的额外权限——即使 grantee 在资源 ACL 中没有任何条目,ShareGrant 也让他临时可读 / 可写。 - ShareGrant 到期或撤销后,grantee 回退到资源 ACL 决定的权限——如果 ACL 里也没有条目,则无权访问。
- ⚠️ ShareGrant 不继承 ACL 树:它只作用于被授权的那一条资源(
resourceId),不沿容器→文档继承传播。 - 详细权限位定义与 ACL 继承规则见 ACL 与继承模式篇。
常见错误码
鉴权创建链路(/v1/share-links/* / /v1/share-grants/*):
| 码 | 名称 | 含义 | 参考 |
|---|---|---|---|
174005 | SHARE_RESOURCE_NOT_FOUND | 分享资源不存在(创建 ShareLink 时) | share-174 |
174006 | SHARE_RESOURCE_TYPE_UNSUPPORTED | 分享资源类型不支持 | share-174 |
174007 | SHARE_TOKEN_GENERATION_FAILED | token 生成失败(服务端异常,重试或联系支持) | share-174 |
公开分享消费侧(/public/s/{tenantCode}/{token}/...):
| 码 | 名称 | 含义 | 参考 |
|---|---|---|---|
174001 | SHARE_LINK_UNAVAILABLE | 链接不可用(不区分具体原因以抗探测) | share-174 |
174008 | SHARE_LINK_QUOTA_EXCEEDED | 访问次数超出 maxAccessCount | share-174 |
174009 | PASSWORD_REQUIRED | 需要密码但未携带(先调 /verify) | share-174 |
174010 | PASSWORD_INVALID | 密码错误 | share-174 |
174011 | PASSWORD_NOT_REQUIRED | 未设密码却传了密码(先看 requiresPassword) | share-174 |
174013 | IP_NOT_ALLOWED | 访问方 IP 不在白名单内 | share-174 |
174014 | SHARE_LINK_PATH_INVALID | CONTAINER 分享 path 参数无效 | share-174 |
常见坑
- ⚠️ 创建 ShareLink 时
permissionBits只含 READ(1)却期望对方能下载文件:公开链路下载要求 DOWNLOAD 位(2);仅 READ 链接访问/download统一返回不可用响应——这是设计约束。如需完整公开下载,创建时将permissionBits设为3(READ + DOWNLOAD)。 - ⚠️ 尝试解析
token结构:token 是平台内部不透明字符串,格式可能随时变化,不应依赖其任何结构属性。 - ⚠️ 用
/download端点替代/list浏览容器:CONTAINER 类型分享不能直接 download 容器本身,需先通过/list拿到子文档列表,再按path下载具体文档。 - ⚠️ grantee 传 IdP 侧 openId / unionId:
granteeId是 ATKONBASE 内部稳定 ID,不是 IdP 原始主键。取法见 认证与身份双通道模式篇。 - ⚠️ ShareGrant 的 permissionPreset 与 ACL role 混用:ShareGrant 预设是临时叠加,不同于 ACL set 端点的
role参数——两者独立维护,不要假设一方变更会同步影响另一方。 - ⚠️ CONTAINER 类型 ShareLink
/list返回不可用响应误以为链接失效:DOCUMENT / VERSION 类型确实不支持浏览,这是正常行为;检查resourceType字段。
下一步
- ACL 权限位、预设角色、grantee 主体 → ACL 与继承模式篇
- TRASHED 状态对分享可达性的影响 → 生命周期模式篇
- V1 端点契约 + Try-it → 接口参考