Google oauth java客户端获取访问令牌失败,错误为;400错误请求{“错误”:“无效请求”};

Google oauth java客户端获取访问令牌失败,错误为;400错误请求{“错误”:“无效请求”};,java,oauth-2.0,google-oauth,Java,Oauth 2.0,Google Oauth,我正在使用此处显示的“web服务器应用程序”示例。在回调servlet中,我希望检索访问令牌,但无法成功地检索。 下面是我的代码 @Override protected String getUserId(HttpServletRequest req) throws ServletException, IOException { // return user ID Iterator<String> iterator = req.getParameterMap

我正在使用此处显示的“web服务器应用程序”示例。在回调servlet中,我希望检索访问令牌,但无法成功地检索。 下面是我的代码

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
      Iterator<String> iterator = req.getParameterMap().keySet().iterator();
        while (iterator.hasNext()) {
            String string = iterator.next();

            System.out.println(string+"---++--"+req.getParameter(string));
        }
        GoogleAuthorizationCodeTokenRequest newTokenRequest = new GoogleAuthorizationCodeFlow.Builder(new NetHttpTransport(), new JacksonFactory(),
                                                             "2XXXXXX7218.apps.googleusercontent.com", "KugD_XXX_7vqnGZVXXXXX1M",
                                                              Collections.singleton("https://gdata.youtube.com"))
                                                              .build().newTokenRequest(req.getParameter("code"));
        //GoogleAuth
        GoogleTokenResponse token = newTokenRequest.setRedirectUri("/").execute();
        String accessToken = token.getAccessToken();
        System.out.println("accesstoken:"+accessToken);
        return "";
  }
简而言之,我得到了“code”参数(请求代码),我不知道如何将其转换为访问令牌。 我已经看过了 但是在我的代码中没有多少东西可以使用

编辑

GoogleAPI不适合我,所以我没有使用任何库就编写了以下代码

 URL url = new URL("https://accounts.google.com/o/oauth2/token");
    connection = (HttpURLConnection) url.openConnection();
    String urlParameters = "code=" + req.getParameter("code") + "&client_id=29852.apps.googleusercontent.com&client_secret=KugD_LVi_7vqnssssxxxNRBz1M"+
            "&redirect_uri=https://flixomnia.com/oauth2callback&grant_type=authorization_code&scope=https://gdata.youtube.com&response_type=token";
    connection.setDoOutput(true);
    connection.setDoInput(true);
    connection.setInstanceFollowRedirects(true);
    connection.setRequestMethod("POST");
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    connection.setRequestProperty("Authorization", "Bearer 4/q3Xh_pJI458XXXXXXXkh-lxe3-8.cmaD6o7V5BkQXE-XXXXX-edgI");
    connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length));
    connection.setRequestProperty("X-GData-Key", "key=AI39siXXXXXXM7tyHBvXEM1lLcORetit6QSArQ3sjelBxXXXXXXtgLSPdZPxvsF_vkntOQMnAEYAuVFqhN7oUw");
    connection.setRequestProperty("GData-Version", "2");

    connection.setUseCaches(false);
    //com.google.gdata.client.youtube.YouTubeService service = new com.google.gdata.client.youtube.YouTubeService("","");
    //YouTubeMediaGroup g = new YouTubeMediaGroup();


    DataOutputStream wr = new DataOutputStream(connection.getOutputStream());

    wr.writeBytes(urlParameters);
    wr.flush();
    InputStream inputStream = connection.getInputStream();
    byte[] b = new byte[1024];
    while (inputStream.read(b) != -1) {
        System.out.print(new String(b));

    }
    System.out.println("");
    wr.close();
    connection.disconnect();
但我仍然得到以下错误

com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
  "error" : "invalid_request"
}
    {  "error" : "invalid_request"}
java.io.IOException: Server returned HTTP response code: 400 for URL: https://accounts.google.com/o/oauth2/token
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1615)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at com.broadcastr.servlets.YouTubeCallbackService.getUserId(YouTubeCallbackService.java:168)
    at com.google.api.client.extensions.servlet.auth.oauth2.AbstractAuthorizationCodeCallbackServlet.doGet(AbstractAuthorizationCodeCallbackServlet.java:130)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

上面的Richard是对的,在setRedirectUri中,您需要使用注册应用程序时指定的完整重定向URI。这不应该是相对的,而应该是绝对的。(希望是https)


davep

在获得一个Java应用程序和一个Android应用程序来访问我的Oauth服务器时,我发现以下两个库很有用——但它们的用途不同——也许其中一个比另一个更适合您的需要

  • google oauth java客户端 用于日常运动, 此库/示例代码允许您从Java访问自己的OAuth2服务器

  • Android中的Auth2流中使用的google api java客户端(Latitude) 此库/示例代码专门用于通过OAuth2访问Google API

  • 我不确定你想解决哪个问题,但这两个问题中的一个应该会有帮助。两者都经历了将“代码”交换为“authToken”的过程,但方式略有不同。 铷

  • 在上面初始代码中获取访问令牌的
    setRedirectUri
    方法中,
    redirecturi
    设置不正确。应使用在客户端注册时指定的
    重定向uri

  • 在编辑代码中,当向访问令牌端点发送所需参数时,不受支持的参数
    response\u type
    也会随请求一起发送。删除
    response\u type
    参数应该可以解决这个问题

    此外,根据,如果请求使用多个机制对客户端进行身份验证,则访问令牌端点也可能会出错
    无效\u请求
    。因此,删除
    URLConnection
    Authorization
    头也可以解决这个问题


  • 请从请求URL中删除“&response\u type=token”参数,该参数是编辑代码中的问题,您的问题将得到解决。

    我还浪费了2天时间来解决此问题。我无法使用
    HttpUrlConnection
    发布令牌请求
    HttpClient
    为我工作

    以下是工作代码:

    1) 传递的值:

    String url = "https://accounts.google.com/o/oauth2/token";
    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
    nameValuePairs.add(new BasicNameValuePair("grant_type", "authorization_code"));
    
    nameValuePairs.add(new BasicNameValuePair("client_id",client_id));
    nameValuePairs.add(new BasicNameValuePair("client_secret", client_secret));
    nameValuePairs.add(new BasicNameValuePair("redirect_uri", "http://example.com/bin/showcase/servlet/googlecallback"));
    nameValuePairs.add(new BasicNameValuePair("code", code));
    
    StringBuffer postResult =  sendPost(url, nameValuePairs);
    
    stringurl=”https://accounts.google.com/o/oauth2/token";
    List nameValuePairs=新的ArrayList(1);
    添加(新的BasicNameValuePair(“授权类型”、“授权代码”);
    添加(新的BasicNameValuePair(“客户端id”,客户端id));
    添加(新的BasicNameValuePair(“客户机密”,客户机密));
    添加(新的BasicNameValuePair(“重定向uri”)http://example.com/bin/showcase/servlet/googlecallback"));
    添加(新的BasicNameValuePair(“代码”,code));
    StringBuffer postResult=sendPost(url,nameValuePairs);
    
    2) 方法

    private-StringBuffer-sendPost(字符串url,列表后参数)
    抛出异常{
    HttpPost=新的HttpPost(url);
    HttpClient=new DefaultHttpClient();
    //添加标题
    post.setHeader(“主机”、“accounts.google.com”);
    post.setHeader(“接受”,
    “text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8”);
    post.setHeader(“接受语言”,“en-US,en;q=0.5”);
    post.setHeader(“连接”、“保持活动”);
    post.setHeader(“Referer”https://accounts.google.com/o/oauth2/token");
    post.setHeader(“内容类型”、“应用程序/x-www-form-urlencoded”);
    post.setEntity(新的UrlEncodedFormEntity(postParams));
    HttpResponse response=client.execute(post);
    int responseCode=response.getStatusLine().getStatusCode();
    BufferedReader rd=新的BufferedReader(
    新的InputStreamReader(response.getEntity().getContent());
    StringBuffer结果=新的StringBuffer();
    String line=“”;`在此处输入代码`
    而((line=rd.readLine())!=null){
    结果。追加(行);
    }
    返回结果;
    }
    
    今晚我刚开始使用google oauth java客户端,但我觉得您没有正确设置回调URI(“/”)。也许在上遵循Servlet授权代码流会有所帮助。我发现示例代码非常有用,但它适用于Java客户机,而不是servlet。祝你好运。不,还是没用,我试过了@RichardBerger看到我的新编辑,它仍然不起作用:(嘿,李察,使用客户端库的好建议,但是,在Android上使用OAuth2的首选方法是谷歌Play服务库。原来的帖子是针对WebServer的,所以这不适用,但是对于你的情况,你应该考虑移动它,作为它的安全性和可用性。戴维:谢谢你的更新。一个问题。从我快速查看您提供的参考资料来看,似乎Google Play服务是访问任何Google API的必经之路,但不是用于访问某些随机的第三方API。这通常是正确的吗?Richard,您是正确的。我们听到了关于使用除Google以外的其他API的请求,但我们没有什么需要说明的谢谢,我想补充一点,页眉对我来说非常重要。
    private StringBuffer sendPost(String url, List<NameValuePair> postParams) 
            throws Exception {
    
        HttpPost post = new HttpPost(url);
        HttpClient client = new DefaultHttpClient();
    
        // add header
        post.setHeader("Host", "accounts.google.com");
        post.setHeader("Accept", 
                "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        post.setHeader("Accept-Language", "en-US,en;q=0.5");
        post.setHeader("Connection", "keep-alive");
        post.setHeader("Referer", "https://accounts.google.com/o/oauth2/token");
        post.setHeader("Content-Type", "application/x-www-form-urlencoded");
    
        post.setEntity(new UrlEncodedFormEntity(postParams));
    
        HttpResponse response = client.execute(post);
    
        int responseCode = response.getStatusLine().getStatusCode();
    
        BufferedReader rd = new BufferedReader(
                new InputStreamReader(response.getEntity().getContent()));
    
        StringBuffer result = new StringBuffer();
        String line = "";`enter code here`
        while ((line = rd.readLine()) != null) {
            result.append(line);
        }
        return result;
    }