2009-08-27 30 views
27

¿Cómo puedo especificar el nombre de usuario y la contraseña para realizar solicitudes de autenticación básica con el servicio URLFetch de App Engine (en Java)?Uso de HTTP Basic-Auth con Google App Engine Servicio URLFetch

Parece que puedo establecer cabeceras HTTP:

URL url = new URL("http://www.example.com/comment"); 
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
connection.setRequestProperty("X-MyApp-Version", "2.7.3");   

¿Cuáles son las cabeceras apropiadas para el sistema-Auth?

+1

¿Es esto realmente una pregunta de App Engine? Simplemente busque los RFC de HTTP para ver cómo hacer la autenticación básica (sugerencia - 'Autorización'). –

+3

Esperaba que pudiera haber un contenedor de conveniencia para App Engine similar a Apache HttpClient para que no tenga que establecer (y codificar base64) el encabezado Authorization manualmente. – Thilo

+0

información muy útil –

Respuesta

30

Ésta es una encabezado de autenticación básica sobre http:

Autorización: Base64 básico codificado (nombre de usuario: contraseña)

por ejemplo:

GET /private/index.html HTTP/1.0 
Host: myhost.com 
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== 

que se necesitan para hacer esto:

URL url = new URL("http://www.example.com/comment"); 
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
connection.setRequestProperty("Authorization", 
"Basic "+codec.encodeBase64String(("username:password").getBytes()); 

Y para ello tendrá que obtener una API códec de base 64, al igual que el Apache Commons Codec

+1

Esto es lo que terminé haciendo. Y como puse el nombre de usuario: contraseña como una propiedad en appengine-web.xml, simplemente puse la versión codificada directamente allí, así que ni siquiera necesito un códec. (Puede usar la línea de comandos de openssl: echo -n "nombre de usuario: contraseña" | openssl enc -base64) – Thilo

+0

+1 esto también resolvió un problema que estaba a punto de tener con la Autenticación HTTP. Gracias. Ah, y getBytes() necesita otro) para cerrar setRequestProperty. –

6

configura un autenticador antes de llamar openConnection() como este,

Authenticator.setDefault(new Authenticator() { 
    protected PasswordAuthentication getPasswordAuthentication() { 
     return new PasswordAuthentication(username, password.toCharArray()); 
    } 
}); 

Dado que sólo hay un autenticador predeterminado global, esto en realidad no funcionan bien cuando hay varios usuarios que realizan el URLFetch en múltiples hilos. Usaría Apache HttpClient si ese es el caso.

EDIT: Estaba equivocado. App Engine no permite el Authenticator. Incluso si está permitido, tendríamos el problema de múltiples hilos con una instancia de autenticación global. Aunque no puede crear subprocesos, es posible que sus solicitudes se publiquen en diferentes subprocesos. Por lo que sólo tiene que añadir la cabecera de forma manual utilizando esta función,

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); 
    } 
+0

Solo hay un hilo en App Engine ... (por cierto, ¿hay alguna documentación que garantice que sea así?) – Thilo

+0

Tuvimos algún problema con esto, pensé que estaba enhebrado. Comprobaré con la persona que implementó esto cuando regrese a la oficina la próxima semana. –

+0

Acabo de hablar con el tipo que portó nuestra aplicación a Google. Ver mis ediciones –

1

Nota sobre la primera respuesta: setRequestProperty debe obtener el nombre de la propiedad sin los dos puntos ("Autorización" en lugar de "Autorización:").

+0

Buena captura, he editado la respuesta. –

14

Para aquellos interesados ​​en hacer esto en Python (como yo), el código es el siguiente:

result = urlfetch.fetch("http://www.example.com/comment", 
         headers={"Authorization": 
           "Basic %s" % base64.b64encode("username:pass")}) 
+0

creo que el código debe ser como sigue: resultado = urlfetch.fetch ( "http://yourserver.com/page/init.php, cabeceras = { "Autorización": "Básico% s" % base64 .encodestring ("nombre de usuario: contraseña") [: - 1] }); –

+1

Debería usar: base64.encodestring ("nombre de usuario: contraseña"). strip() –

+0

Actualizado para usar base64.b64encode. Sé que funciona porque es lo que realmente estaba usando en mi código real. –

4

Usando HttpURLConnection me dio algunos problemas (por alguna razón el servidor que estaba tratando de conectar con dejase 't acepta las credenciales de autenticación), y finalmente me di cuenta de que en realidad es mucho más fácil hacer uso de la API de bajo nivel URLFetch de GAE (com.google.appengine.api.urlfetch) de esta manera:

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

Esto funcionó.

+0

Esta debería ser la respuesta aceptada, también puede establecer el tiempo de espera: FetchOptions fetchOptions = FetchOptions.Builder.withDeadline (10); HTTPRequest req = new HTTPRequest (fetchurl, HTTPMethod.GET, fetchOptions); – ZiglioUK