我正在使用此处显示的“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 "";
}
运行此代码后,我收到以下错误
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_request"
}
简而言之,我得到“代码”参数(请求代码)我不知道如何将其转换为Access令牌。 我已经看过了 Google API - request for token from Oauth2 returns "invalid_request" Google OAuth 2: response_type error on token request但我的代码中没有太多可用的东西
修改
google API对我不起作用,所以我在不使用任何库的情况下编写了以下代码
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();
但我仍然得到以下错误
{ "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)
答案 0 :(得分:5)
在上面的初始代码中的setRedirectUri
方法中获取访问令牌,redirect_uri
未正确设置。应使用客户注册时指定的redirect_uri
。
在EDIT代码中,在将所需参数发送到访问令牌端点时,还会与请求一起发送不受支持的参数response_type
。删除response_type
参数应该可以解决问题。
此外,根据OAuth2 RFC draft,如果请求使用多种机制对客户端进行身份验证,则访问令牌端点也可能出错invalid_request
。因此,将Authorization
标题移除到URLConnection
也应该可以解决问题。
答案 1 :(得分:2)
我也浪费了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);
2)方法
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;
}
答案 2 :(得分:0)
上面的Richard是正确的,在setRedirectUri中,您需要使用您在注册应用程序时指定的完整重定向URI。那不应该是相对的,而是绝对的。 (并希望https)
davep
答案 3 :(得分:0)
在获取Java应用程序和Android应用程序以访问我的Oauth服务器时,我发现以下两个库很有用 - 但它们用于不同的目的 - 也许一个更适合您的需求而不是另一个。
谷歌OAuth的Java的客户端 用于DailyMotion。 https://code.google.com/p/google-oauth-java-client/,http://samples.google-oauth-java-client.googlecode.com/hg/dailymotion-cmdline-sample/instructions.html 此库/示例代码允许您从Java访问自己的OAuth2服务器。
google-api-java-client用于:Android中的Auth2流程(纬度)http://blog.doityourselfandroid.com/2011/08/06/oauth-2-0-flow-android/ 此库/示例代码专门用于通过OAuth2访问Google API。
我不确定你要解决哪个问题,但其中一个应该有所帮助。两者都经历了为“authToken”交换“代码”的过程,但方式略有不同。 RB
答案 4 :(得分:0)
请从EDIT代码中存在问题的请求网址中删除“&amp; response_type = token”参数,问题就解决了。