SpringBoot + OAuth2 获取授权码时的踩坑记录

异常背景

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. 源码断点分析

  1. 异常所处类
    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");
    		}
    		
    		···
    	}
    
    1. 断点分析
      断点位置:
    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,还有其他参数也要根据源码更正过来。

写在最后

所以我们在通过网上的课程学习技术的时候一定要辩证看待,多查资料,对比学习。注意细节。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值