【发布时间】:2014-12-11 20:19:08
【问题描述】:
我正在尝试为Reddit's Api 创建一个扩展。 Reddit 遵循 OAuth 2 来获取 access_token。我正在使用 springs RestTemplate 向 Reddit 发出所有 POST 请求。我能够根据文档成功完成第一阶段。用户被重定向到他/她允许我的应用程序的 Reddit,然后 Reddit 使用代码将我重定向回我的应用程序。但是,第二阶段似乎不起作用。我必须使用该代码发出另一个帖子请求:
https://ssl.reddit.com/api/v1/access_token
这是我获取 AccessGrant(从 Reddit 发回的访问令牌的 SpringSocial 包装器)的尝试。 Spring Social 要求您扩展 OAuth2Template 并从那里实现身份验证过程。在典型的 Spring 应用中,控制器会使用 helper 调用 RedditOAuth2Template.exchangeForAccess 并将返回的 AccessGrant 保存到数据库中。
根据 Reddit API Documentaiton,由于缺少通过 HTTP 基本身份验证的客户端凭据,会发生 401 响应。但是,我在 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);
}
}
【问题讨论】:
标签: spring oauth-2.0 spring-social resttemplate reddit