异常背景
1 Springboot[1.5.15.RELEASE] + OAuth2[2.0.15.RELEASE]
2 获取授权码时
localhost:8080/oauth/authorize?clientid=clientapp&responsetype=code&scope=readuserinfo&redirecturi=https://www.baidu.com
3 浏览器界面异常:
error=“invalid_client”, error_description=“Bad client credentials”
4 后台打印异常:
2019-10-07 20:49:57.306 INFO 7804 — [nio-8080-exec-3] o.s.s.o.p.e.AuthorizationEndpoint : Handling ClientRegistrationException error: No client with requested id: null
异常分析
1. 三问度娘
1> No client with requested id: null
2> error=“invalid_client”, error_description=“Bad client credentials”
3> Bad client credentials
三问无果
2. 源码断点分析
-
异常所处类
o.s.s.o.p.e.AuthorizationEndpoint 即为抛出异常的类
进入该类即可发现获取授权码的接口@RequestMapping(value = "/oauth/authorize") public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters, SessionStatus sessionStatus, Principal principal) { // Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should // query off of the authorization request instead of referring back to the parameters map. The contents of the // parameters map will be stored without change in the AuthorizationRequest object once it is created. AuthorizationRequest authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters); Set<String> responseTypes = authorizationRequest.getResponseTypes(); if (!responseTypes.contains("token") && !responseTypes.contains("code")) { throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes); } if (authorizationRequest.getClientId() == null) { throw new InvalidClientException("A client id must be provided"); } ··· }
- 断点分析
断点位置:
Set<String> responseTypes = authorizationRequest.getResponseTypes();
发现没有进入就异常了。必然是在该接口的第一行出现的异常即:
AuthorizationRequest authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters);
进入方法
getOAuth2RequestFactory()
:无法分析出异常出现的地方protected OAuth2RequestFactory getOAuth2RequestFactory() { return oAuth2RequestFactory; }
继续,进入方法
createAuthorizationRequest(parameters)
:public AuthorizationRequest createAuthorizationRequest(Map<String, String> authorizationParameters) { String clientId = authorizationParameters.get(OAuth2Utils.CLIENT_ID); String state = authorizationParameters.get(OAuth2Utils.STATE); String redirectUri = authorizationParameters.get(OAuth2Utils.REDIRECT_URI); Set<String> responseTypes = OAuth2Utils.parseParameterList(authorizationParameters .get(OAuth2Utils.RESPONSE_TYPE)); Set<String> scopes = extractScopes(authorizationParameters, clientId); AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections.<String, String> emptyMap(), clientId, scopes, null, null, false, state, redirectUri, responseTypes); ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); request.setResourceIdsAndAuthoritiesFromClientDetails(clientDetails); return request; }
关注第一行代码,发现所需clientId正是从我们的请求url中获取,但是获取的属性名并不是我们输入的clientid 而是 client_id:
String clientId = authorizationParameters.get(OAuth2Utils.CLIENT_ID);
/** * Constant to use while parsing and formatting parameter maps for OAuth2 requests */ public static final String CLIENT_ID = "client_id";
真的是个大错误啊,由于该url是按照课程给的进行请求的,这位老师可能是粘贴的时候出了错,因为看他课程后面的贴图是请求成功的。写到这里我就要责问自己了:后面贴图的请求地址为什么没有仔细看啊,真是该!!
让我羞耻的把原课程截图出来吧—[是我为自己的笨感到羞耻]—:
除了参数client_id,还有其他参数也要根据源码更正过来。 - 断点分析
写在最后
所以我们在通过网上的课程学习技术的时候一定要辩证看待,多查资料,对比学习。注意细节。