Mock 地址安全加固:空间 ID → 16 位随机 mock_token
- 问题:/mock/{自增空间ID} 可枚举且服务绑定所有网卡,局域网可猜他人空间
- workspaces 新增 mock_token(UNIQUE,随机 8 字节 hex;老库自动 ALTER + 回填)
- /mock/{token}/path:解析失败统一 404(不暴露存在性);限流 key 沿用 token
- /api/me 与发布响应返回 token 形态 base;弹窗 URL 改用 token
- 验证:token URL 正常随机生成;旧数字 ID 与任意伪造 token 均 404
This commit is contained in:
1 parent
d9ccccd280
commit
0edd3e674a
9 files changed
+87
-17
No files matched your search
@@ -3,7 +3,15 @@
|
||||
*/
|
||||
export type AccountUser = { id: number; name: string; email: string };
|
||||
export type AccountTeam = { id: number; name: string; role: string; owner: string };
|
||||
export type AccountWorkspace = { id: number; name: string; teamId: number | null; ownerId: number; updatedAt: number };
|
||||
export type AccountWorkspace = {
|
||||
id: number;
|
||||
name: string;
|
||||
teamId: number | null;
|
||||
ownerId: number;
|
||||
updatedAt: number;
|
||||
/** Mock 服务随机地址片段(不可枚举) */
|
||||
mockToken?: string;
|
||||
};
|
||||
|
||||
class ApiError extends Error {
|
||||
constructor(message: string, public status: number) {
|
||||
|
||||
@@ -36,7 +36,8 @@ export function MockLinkDialog({ node }: { node: HttpApiNode }) {
|
||||
}
|
||||
}
|
||||
|
||||
const mockUrl = space ? `${location.origin.replace(/:\d+$/, ":8787")}/mock/${space.id}${urlPath}` : "";
|
||||
const mockSeg = space?.mockToken ?? (space ? String(space.id) : "");
|
||||
const mockUrl = mockSeg ? `${location.origin.replace(/:\d+$/, ":8787")}/mock/${mockSeg}${urlPath}` : "";
|
||||
|
||||
const publish = async () => {
|
||||
if (!account.token || !space) return;
|
||||
|
||||
@@ -133,7 +133,7 @@ type WorkspaceStore = PersistedShape & {
|
||||
token: string | null;
|
||||
user: { id: number; name: string; email: string } | null;
|
||||
teams: { id: number; name: string; role: string; owner: string }[];
|
||||
spaces: { id: number; name: string; teamId: number | null; updatedAt: number }[];
|
||||
spaces: { id: number; name: string; teamId: number | null; updatedAt: number; mockToken?: string }[];
|
||||
activeSpaceId: number | null;
|
||||
syncing: boolean;
|
||||
lastSyncAt: number | null;
|
||||
|
||||
Reference in new issue
Block a user