播放框架,设置HTTP POST请求标头

时间:2014-10-12 16:53:49

标签: java web-services oauth playframework google-api

问题

在Play Framework中使用Google Plus登录Api时,您是否必须以不同的方式设置标题?我在这里做错了吗?

背景

我使用Play Framework(在Java中)使用Google Plus Sign in Api 我在OAuth身份验证的第二站遇到问题,将Authorization CodeToken进行了交换。

基本OAuth流程

Pretty Picture

  1. 将用户重定向到User login/Consent screen
    • 这会询问用户是否要授予您对所请求范围的应用程序权限
    • 网址:https://accounts.google.com/o/oauth2/auth
  2. Authorization Code兑换Token
    • 如果用户授予您的应用程序权限,那么他们将被重定向到您指定的网址,该网址(作为GET参数)将为Authorization Code
    • 然后,您的应用可以使用此Authoriztion Code从服务器获取Token
    • 您的应用程序通过向Google服务器上的端点发出HTTP请求(或者您正在使用的任何服务)来执行此操作
      • 网址:https://accounts.google.com/o/oauth2/token
  3. 在API请求中使用Token
  4. 问题

    要使用Google Plus登录Api与Authorization Code兑换Token,您必须向POST发出https://accounts.google.com/o/oauth2/token个请求,其中包含以下周长

    {
      "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 Library。我提出这样的请求

    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
    }
    

    如您所见,我设置标题grant_type。为了确保设置标头正常工作,我创建了一个程序,在NodeJS(Source)中吐出请求的标头,这就是结果

    {
      "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"
      }
    }
    

1 个答案:

答案 0 :(得分:1)

我认为这些不是作为标题发送而是作为正文发送。在您提供的链接中有一个示例:

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());