2014-10-16 29 views
0

我正在嘗試爲Reddit's Api創建擴展名。 Reddit遵循OAuth 2獲取access_token。我正在使用RestTemplate彈簧來發送所有對Reddit的POST請求。根據文檔,我能夠成功完成第一階段。用戶被重定向到Reddit,在那裏他/她允許我的應用程序,Reddit然後通過代碼將我重新導向到我的應用程序。但是,第二階段似乎並不奏效。我必須使用代碼來使另一個職位要求:Spring Social Reddit擴展 - OAuth 2 Access_token檢索。 401錯誤

https://ssl.reddit.com/api/v1/access_token

這裏是我獲得AccessGrant(SpringSocial包裝器的accessToken從reddit的發回)的嘗試。 Spring Social需要你擴展OAuth2Template並從那裏實現認證過程。在典型的Spring應用程序中,控制器將使用助手來調用RedditOAuth2Template.exchangeForAccess並將返回的AccessGrant保存到數據庫中。

根據Reddit API文檔401響應由於缺乏客戶端憑證通過HTTP基本身份驗證發生。但是,我在createHeaders(String username,String password)方法中這樣做。

公共類RedditOAuth2Template擴展OAuth2Template {

private static final Logger LOG = LogManager.getLogger(RedditOAuth2Template.class); 

private String client_id; 
private String client_secret; 

public RedditOAuth2Template(String clientId, String clientSecret) { 
    super(clientId, clientSecret, RedditPaths.OAUTH_AUTH_URL, RedditPaths.OAUTH_TOKEN_URL); 
    this.client_id = clientId; 
    this.client_secret = clientSecret; 
    setUseParametersForClientAuthentication(true); 
} 


@Override 
@SuppressWarnings({"unchecked", "rawtypes"}) 
protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) { 
    HttpHeaders headers = createHeaders(client_id, client_secret); 
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 
    headers.set(accessTokenUrl, accessTokenUrl); 
    HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(parameters, headers); 
    ResponseEntity<Map> responseEntity = getRestTemplate().exchange(accessTokenUrl, HttpMethod.POST, requestEntity, Map.class); 
    Map<String, Object> responseMap = responseEntity.getBody(); 
    return extractAccessGrant(responseMap); 
} 

/* 
Reddit requires client_id and client_secret be 
placed via HTTP basic Auth when retrieving the access_token 
*/ 
private HttpHeaders createHeaders(String username, String password) { 
    String auth = username + ":" + password; 
    byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII"))); 
    HttpHeaders headers = new HttpHeaders(); 
    String authHeader = "Basic " + new String(encodedAuth); 
    headers.set("Authorization", authHeader); 
    return headers; 
} 

private AccessGrant extractAccessGrant(Map<String, Object> result) { 
    String accessToken = (String) result.get("access_token"); 
    String scope = (String) result.get("scope"); 
    String refreshToken = (String) result.get("refresh_token"); 
    // result.get("expires_in") may be an Integer, so cast it to Number first. 
    Number expiresInNumber = (Number) result.get("expires_in"); 
    Long expiresIn = (expiresInNumber == null) ? null : expiresInNumber.longValue(); 

    return createAccessGrant(accessToken, scope, refreshToken, expiresIn, result); 
} 

}

回答

0

如果您收到該端點401響應,你正在做的少數事情之一錯誤,凡是涉及到發送的客戶機ID &祕密作爲HTTP基本授權:

  • 不包括適當格式化的授權報頭(即,Authorization: basic <b64 encoded credentials>
  • 不正確Base 64編碼憑據
  • 不包括一個CLIENT_ID,對於一個有效OAuth2用戶端
  • 不包括客戶端ID和祕密之間的分號
  • 不包括的祕密,或者包括了錯誤的祕密

您應該檢查基本客戶端身份驗證的每個階段,並在每個階段記錄您的輸出(或使用調試器來檢查它)以確保您不會丟失任何東西。您還應該檢查您生成的實際HTTP請求,並驗證頭文件是否正在發送(某些HTTP庫喜歡自由地使用頭文件)