{"record":{"id":"f717687b181c8f90","repo":"paascloud/paascloud-master","slug":"client-f71768","errorCode":null,"errorMessage":"请求头中无client信息","messagePattern":"请求头中无client信息","errorType":"exception","errorClass":"UnapprovedClientAuthenticationException","httpStatus":null,"severity":"error","filePath":"paascloud-provider/paascloud-provider-uac/src/main/java/com/paascloud/provider/web/admin/UacUserLoginController.java","lineNumber":109,"sourceCode":"\t/**\n\t * 刷新token.\n\t *\n\t * @param request      the request\n\t * @param refreshToken the refresh token\n\t * @param accessToken  the access token\n\t *\n\t * @return the wrapper\n\t */\n\t@GetMapping(value = \"/auth/user/refreshToken\")\n\t@ApiOperation(httpMethod = \"POST\", value = \"刷新token\")\n\tpublic Wrapper<String> refreshToken(HttpServletRequest request, @RequestParam(value = \"refreshToken\") String refreshToken, @RequestParam(value = \"accessToken\") String accessToken) {\n\t\tString token;\n\t\ttry {\n\t\t\tPreconditions.checkArgument(org.apache.commons.lang3.StringUtils.isNotEmpty(accessToken), \"accessToken is null\");\n\t\t\tPreconditions.checkArgument(org.apache.commons.lang3.StringUtils.isNotEmpty(refreshToken), \"refreshToken is null\");\n\t\t\tString header = request.getHeader(HttpHeaders.AUTHORIZATION);\n\t\t\tif (header == null || !header.startsWith(BEARER_TOKEN_TYPE)) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"请求头中无client信息\");\n\t\t\t}\n\t\t\tString[] tokens = RequestUtil.extractAndDecodeHeader(header);\n\t\t\tassert tokens.length == 2;\n\n\t\t\tString clientId = tokens[0];\n\t\t\tString clientSecret = tokens[1];\n\n\t\t\tClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);\n\n\t\t\tif (clientDetails == null) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"clientId对应的配置信息不存在:\" + clientId);\n\t\t\t} else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {\n\t\t\t\tthrow new UnapprovedClientAuthenticationException(\"clientSecret不匹配:\" + clientId);\n\t\t\t}\n\n\t\t\ttoken = uacUserTokenService.refreshToken(accessToken, refreshToken, request);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"refreshToken={}\", e.getMessage(), e);","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/paascloud/paascloud-master/blob/781281a9503332ed3cef44ea618349d14230a127/paascloud-provider/paascloud-provider-uac/src/main/java/com/paascloud/provider/web/admin/UacUserLoginController.java#L91-L127","documentation":"UnapprovedClientAuthenticationException (Spring Security OAuth) with message '请求头中无client信息' thrown by UacUserLoginController.refreshToken when the HTTP Authorization header is absent or does not start with the 'Basic ' (BEARER_TOKEN_TYPE constant as used here) prefix. The controller requires a Basic-auth client header to identify the OAuth2 client before refreshing a token.","triggerScenarios":"POST to the refreshToken endpoint without an Authorization header, or with a header not starting with the expected prefix (e.g. sending only the access token as a bare header, or 'Bearer xxx' instead of Basic base64(clientId:clientSecret)).","commonSituations":"Frontend strips the Authorization header via a proxy or CORS preflight handling; developer sends the access token without Basic client credentials; gateway removes auth headers; client credentials missing in mobile/SPA configuration.","solutions":["Send an HTTP Basic Authorization header with base64(clientId:clientSecret), e.g. Authorization: Basic Y2xpZW50SWQ6c2VjcmV0","Verify the gateway/proxy forwards the Authorization header to the UAC service","Confirm the OAuth client id/secret configured in the frontend match a registered ClientDetails","Check the expected header prefix in this codebase (BEARER_TOKEN_TYPE constant) and match it exactly"],"exampleFix":"// before\nrequest without Authorization header\n// after\nAuthorization: Basic bWFsbC1hZG1pbjphZG1pbg==  // base64(clientId:clientSecret)","handlingStrategy":"try-catch","validationCode":"const header = headers['Authorization'];\nif (!header || !header.startsWith('Basic ')) { failFast('missing Basic Authorization header'); }","typeGuard":"function hasBasicAuth(header) { return typeof header === 'string' && header.startsWith('Basic '); }","tryCatchPattern":"try { await refreshToken(token, headers); }\ncatch (e) {\n  if (String(e.message).includes('client信息')) {\n    // re-login or re-attach Basic auth credentials\n  }\n}","preventionTips":["Always send Authorization: Basic base64(clientId:clientSecret) on token refresh calls","Verify proxies/gateways forward the Authorization header","Centralize token-refresh logic so headers are never forgotten","Check CORS preflight does not strip Authorization"],"tags":["oauth2","http-headers","authentication"],"backgroundTag":"authentication-required","analyzedSha":"781281a9503332ed3cef44ea618349d14230a127","analyzedAt":"2026-09-10T10:59:02.070Z","contentChangedAt":"2026-09-10T10:59:02.070Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}