Использование HTTP Basic-Auth с сервисом UrlFetch Google App Engine
-
20-09-2019 - |
Вопрос
Как я могу указать имя пользователя и пароль для выполнения запросов Basic-Auth с помощью App Engine Выборка URL - адресов сервис (на Java)?
Кажется, я могу установить HTTP-заголовки:
URL url = new URL("http://www.example.com/comment");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("X-MyApp-Version", "2.7.3");
Каковы подходящие заголовки для Basic-Auth?
Решение
Это базовый заголовок авторизации по протоколу http:
Авторизация:Базовая кодировка base64 (имя пользователя: пароль)
например:
GET /private/index.html HTTP/1.0
Host: myhost.com
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Вам нужно будет сделать это:
URL url = new URL("http://www.example.com/comment");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization",
"Basic "+codec.encodeBase64String(("username:password").getBytes());
И для этого вам нужно будет получить base64 codec api, например Кодек Apache Commons для общего доступа
Другие советы
Для тех, кто заинтересован в том, чтобы сделать это на Python (как и я), код выглядит следующим образом:
result = urlfetch.fetch("http://www.example.com/comment",
headers={"Authorization":
"Basic %s" % base64.b64encode("username:pass")})
Вы настраиваете аутентификатор перед вызовом openConnection() следующим образом,
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
});
Поскольку существует только один глобальный аутентификатор по умолчанию, это не очень хорошо работает, когда несколько пользователей выполняют выборку URL в нескольких потоках.Я бы использовал Apache HttpClient, если это так.
Редактировать:Я был неправ.Движок приложений не разрешает аутентификацию.Даже если бы это было разрешено, у нас возникла бы многопоточная проблема с экземпляром global authenticator.Даже если вы не можете создавать потоки, ваши запросы все равно могут обслуживаться в разных потоках.Поэтому мы просто добавляем заголовок вручную, используя эту функцию,
import com.google.appengine.repackaged.com.google.common.util.Base64;
/**
* Preemptively set the Authorization header to use Basic Auth.
* @param connection The HTTP connection
* @param username Username
* @param password Password
*/
public static void setBasicAuth(HttpURLConnection connection,
String username, String password) {
StringBuilder buf = new StringBuilder(username);
buf.append(':');
buf.append(password);
byte[] bytes = null;
try {
bytes = buf.toString().getBytes("ISO-8859-1");
} catch (java.io.UnsupportedEncodingException uee) {
assert false;
}
String header = "Basic " + Base64.encode(bytes);
connection.setRequestProperty("Authorization", header);
}
Используя HttpURLConnection
вызвал у меня некоторые проблемы (по какой-то причине сервер, к которому я пытался подключиться, не принимал учетные данные для авторизации), и, наконец, я понял, что на самом деле это намного проще сделать, используя низкоуровневый API UrlFetch GAE (com.google.appengine.api.urlfetch
) вот так:
URL fetchurl = new URL(url);
String nameAndPassword = credentials.get("name")+":"+credentials.get("password");
String authorizationString = "Basic " + Base64.encode(nameAndPassword.getBytes());
HTTPRequest request = new HTTPRequest(fetchurl);
request.addHeader(new HTTPHeader("Authorization", authorizationString));
HTTPResponse response = URLFetchServiceFactory.getURLFetchService().fetch(request);
System.out.println(new String(response.getContent()));
Это сработало.
В Apache HttpClient есть оболочка для App Engine
пожалуйста, просмотрите сообщение http://esxx.blogspot.com/2009/06/using-apaches-httpclient-on-google-app.html
http://peterkenji.blogspot.com/2009/08/using-apache-httpclient-4-with-google.html
Обратите внимание на первый ответ:setRequestProperty должен получить имя свойства без двоеточия ("Авторизация", а не "Авторизация:").