问题
在 Play Framework 中使用 Google Plus Sign In Api 时,是否必须以不同的方式设置 header ?我在这里做错了什么吗?
背景
我正在使用Play Framework (在 Java 中)使用 Google Plus Sign in Api .
我在 OAuth 身份验证的第二阶段遇到问题,将授权代码
交换为 token
。
基本 OAuth 流程
- 将用户重定向至
用户登录/同意屏幕
- 这会询问用户是否要向您授予对所请求范围的应用程序权限
- 网址:
https://accounts.google.com/o/oauth2/auth
- 用
授权代码
交换token
- 如果用户授予您的应用程序权限,那么他们将被重定向到您指定的 URL,该 URL(作为
GET
参数)将是一个授权代码
。 - 您的应用程序随后可以使用此
授权代码
从服务器获取token
- 您的应用程序通过向 Google 服务器(或您正在使用的任何服务)上的端点发出 HTTP 请求来实现此目的
- 网址:
https://accounts.google.com/o/oauth2/token
- 网址:
- 如果用户授予您的应用程序权限,那么他们将被重定向到您指定的 URL,该 URL(作为
- 在 API 请求中使用
token
问题
要使用 Google Plus 登录 Api 将授权代码
交换为 token
,您必须使用以下范围向 https://accounts.google.com/o/oauth2/token
发出 POST
请求
{
"code": "Security Code Returned from Step 1",
"client_id": "Client Id that was given to you in GApi Console",
"client_secret": "Client Secret that was given to you in the GApi Console",
"redirect_uri": "Redirect Uri you specified in the GApi Console",
"grant_type": "authorization_code"
}
但是,当我使用所有正确的参数发出此请求时,我收到此错误
{
"error" : "invalid_request",
"error_description" : "Required parameter is missing: grant_type"
}
通过 Google Plus 登录 Api
要在 Play 框架中发出 HTTP 请求,您可以使用 WS 库
。我这样提出请求
public static F.Promise<Result> OAuthCallback(String state, String code){
/*
Note:
- The GoogleStrategy class is just a class that holds all my GApi credentials
- The parameters (String state, String code) are just GET params from Step 1, returned by the GApi
*/
//Make URL builder
WSRequestHolder requestHolder = WS.url(GoogleStrategy.getTokenUrl);
//Set headers
requestHolder.setHeader("code", code);
requestHolder.setHeader("client_id", GoogleStrategy.clientId);
requestHolder.setHeader("client_secret", GoogleStrategy.clientSecret);
requestHolder.setHeader("redirect_uri", GoogleStrategy.redirectUri);
requestHolder.setHeader("grant_type", GoogleStrategy.grantType);//GoogleStrategy.grantType = "authorization_code"
//Make HTTP request and tell program what to do once the HTTP request is finished
F.Promise<Result> getTokenPromise = requestHolder.post("").map(
new F.Function<WSResponse, Result>() {
public Result apply(WSResponse response){
return ok(response.asJson());//Returning result for debugging
}
}
);
return getTokenPromise;//Return promise, Play Framework will handle the Asynchronous stuff
}
如您所见,我设置了 header grant_type
。为了确保设置 header 有效,我编写了一个程序,在 NodeJS( Source ) 中吐出请求的 header ,这就是结果
{
"HEADERS": {
"host": "127.0.0.1:3000",
"code": "4/qazYoReIJZAYO9izlTjjJA.gihwUJ6zgoERgtL038sCVnsvSfAJkgI",
"grant_type": "authorization_code",
"client_secret": "XXXX-CENSORED FOR SECURITY PURPOSES-XXX",
"redirect_uri": "http://127.0.0.1:9000/api/users/auth/google/callback",
"client_id": "XXXX-CENSORED FOR SECURITY PURPOSES-XXX",
"content-type": "text/plain; charset=utf-8",
"connection": "keep-alive",
"accept": "*/*",
"user-agent": "NING/1.0",
"content-length": "14"
}
}
最佳答案
我认为这些内容不应作为 header 发送,而是作为正文发送。在您提供的链接中有一个示例:
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code
因此将它们传递给您的 post
调用:
StringBuilder sb = new StringBuilder();
sb.append("code=").append(code)
.append("&client_id=").append(GoogleStrategy.clientId)
.append("&client_secret=").append( GoogleStrategy.clientSecret)
.append("&redirect_uri=").append(GoogleStrategy.redirectUri)
.append("&grant_type=").append(GoogleStrategy.grantType)
requestHolder.setContentType("application/x-www-form-urlencoded")
.post(sb.toString());
关于java - Play框架,设置HTTP POST请求头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26327602/