{"record":{"id":"e0cb3ac9981b99ae","repo":"jeecgboot/JeecgBoot","slug":"token","errorCode":null,"errorMessage":"token无效","messagePattern":"token无效","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"jeecgboot-vue3/src/views/super/online/cgform/share/store/shareStore.ts","lineNumber":41,"sourceCode":"    },\n    getDataRecord(): Nullable<Recordable> {\n      return this.dataRecord;\n    },\n\n  },\n  actions: {\n\n    // 检查 url 参数是否携带token\n    async checkUrlToken(): Promise<boolean> {\n      const token = new URLSearchParams(window.location.search).get('token');\n      const flag = token != null && token.length > 0;\n      if (flag) {\n        userStore.setToken(token);\n        // 检查 token 是否有效\n        try {\n          const res = await getUserInfo();\n          if (!res?.userInfo) {\n            throw new Error('token无效');\n          } else {\n            userStore.setUserInfo(res.userInfo)\n            if (res.sysAllDictItems) {\n              userStore.setAllDictItems(res.sysAllDictItems);\n            }\n          }\n          return true;\n        } catch (e) {\n          userStore.setToken('');\n          removeCacheByDynKey(TOKEN_KEY)\n          return false;\n        }\n      }\n      return flag;\n    },\n\n    setCgformRecord(value: Nullable<Recordable>) {\n      this.cgformRecord = value;","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecgboot-vue3/src/views/super/online/cgform/share/store/shareStore.ts#L23-L59","documentation":"In the Online cgform 'share' feature (a public link view), checkUrlToken() reads a `token` query param from the URL, sets it as the auth token, then calls getUserInfo() to validate. If getUserInfo() returns no userInfo object, the token is treated as invalid/expired and the error is thrown (but caught immediately, so it does not propagate — it returns false). The token is cleared and cache removed in the catch block, causing the share view to show an unauthenticated/failed state.","triggerScenarios":"Opening a shared online-cgform link whose `?token=...` query param is expired, revoked, malformed, or for a deleted/disabled user. Also when the backend user service is down and getUserInfo() returns a partial/empty response.","commonSituations":"Shared report/form links that have expired; tokens generated by an older signing key after a key rotation; backend getUserInfo endpoint returning success:false with no userInfo; network/proxy issues causing an empty response that bypasses the axios success check.","solutions":["Regenerate or re-issue the share token from the source system and update the link.","Verify the token's signing key matches the backend's current secret (check application.yml jwt config).","Check that the backend /sys/user/getUserInfo returns userInfo for that token (test via Postman).","If the user was deleted/disabled, re-enable or re-share from an active user."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate token shape before relying on it\nconst token = new URLSearchParams(window.location.search).get('token');\nif (!token || token.split('.').length !== 3) {\n  showShareError('Invalid or missing token');\n  return;\n}","typeGuard":"const isValidJwtShape = (t: string | null): boolean =>\n  !!t && t.split('.').length === 3 && token.length > 0;","tryCatchPattern":"// shareStore.checkUrlToken already catches internally; consume the boolean\nconst ok = await shareStore.checkUrlToken();\nif (!ok) { showShareError('Token expired or invalid'); }","preventionTips":["Regenerate share tokens before they expire.","Keep JWT signing keys in sync across deployments.","Show a clear 'link expired' UI when checkUrlToken returns false."],"tags":["auth","token","online-cgform","share","frontend"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}