我有一个带有需要身份验证的端点的 GAE 应用程序,我从应用程序(而不是在浏览器中)调用它。
这是来自 web.xml 的端点的 GAE 规范
<!-- Secure sensitive URLs -->
<security-constraint>
<web-resource-collection>
<url-pattern>/gcm/home</url-pattern>
<url-pattern>/gcm/send</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
以前,在客户端应用程序中,我在调用端点之前使用 ClientLogin 向 Google 进行身份验证。这是我使用的代码,它提取“Auth”令牌,然后将其用作 HTTP GET 上的 Cookie 到上述端点。
public static String loginToGoogle(String userid, String password,
String appUrl) throws Exception {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(
"https://www.google.com/accounts/ClientLogin");
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("accountType", new StringBody("HOSTED_OR_GOOGLE",
"text/plain", Charset.forName("UTF-8")));
reqEntity.addPart("Email", new StringBody(userid));
reqEntity.addPart("Passwd", new StringBody(password));
reqEntity.addPart("service", new StringBody("ah"));
reqEntity.addPart("source", new StringBody("WWWWmyappname"));
post.setEntity(reqEntity);
HttpResponse response = client.execute(post);
if (response.getStatusLine().getStatusCode() == 200) {
InputStream input = response.getEntity().getContent();
String result = IOUtils.toString(input);
String authToken = getAuthToken(result);
post = new HttpPost(appUrl + "/_ah/login?auth=" + authToken);
response = client.execute(post);
Header[] cookies = response.getHeaders("SET-COOKIE");
for (Header cookie : cookies) {
if (cookie.getValue().startsWith("ACSID=")) {
return cookie.getValue();
}
}
throw new Exception("ACSID cookie cannot be found");
} else
throw new Exception("Error obtaining ACSID");
}
private static String getAuthToken(String responseText) throws Exception {
LineNumberReader reader = new LineNumberReader(new StringReader(
responseText));
String line = reader.readLine();
while (line != null) {
line = line.trim();
if (line.startsWith("Auth=")) {
return line.substring(5);
}
line = reader.readLine();
}
throw new Exception("Could not find Auth token");
}
由于 ClientLogin 已被弃用然后被删除,我相信我有义务切换到 OAuth2。阅读文档让我相信我需要一个用于此目的的服务帐户,我在 GAE 的 Google 控制台中适当地设置了它。尽管 GoogleCredential 构建器成功返回了授权令牌,但如果我随后在对端点的 HTTP get 调用中使用该令牌,则响应始终是 Google 登录页面。
为什么,如果我使用令牌,GAE 不会认为我已登录并获得授权?我做这一切都是错的还是错过了一步?
下面是尝试通过 Google 进行身份验证然后调用 GAE 端点的代码:
String emailAddress = "XXXXXXXX@developer.gserviceaccount.com";
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
String emailScope = "https://www.googleapis.com/auth/userinfo.email";
String keyFileName = "YYYYY.p12";
String baseURL = "http://ZZZZZ.appspot.com";
HttpTransport httpTransport;
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
File keyFile = new File(keyFileName);
if(!keyFile.exists()) {
System.err.println("Key file "+keyFileName+" missing");
System.exit(0);
}
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(emailAddress)
.setServiceAccountScopes(Collections.singleton(emailScope))
.setServiceAccountPrivateKeyFromP12File(keyFile)
.build();
boolean success = credential.refreshToken();
System.out.println("Access token refresh "+ success);
String token = credential.getAccessToken();
System.out.println("Token "+token);
String uri = "http://ZZZZZ.appspot.com/gcm/home";
System.out.println("uri: " + uri);
HttpGet get = new HttpGet(uri);
get.setHeader("Cookie", token);
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(get);
response.getEntity().writeTo(System.out);
典型输出:
Access token refresh true
Token ya29.xQGG1kxxxxxxxxxxxxxxxxxxx
uri: http://ZZZZZ.appspot.com/gcm/home
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=300, initial-scale=1" name="viewport">
<meta name="google-site-verification" content="LrdTUW9psUAMbh4Ia074-BPEVmcpBxF6Gwf0MSgQXZs">
<title>Sign in - Google Accounts</title>
.....
谢谢!