2009-08-27 6 views
27

Come specificare il nome utente e la password per effettuare richieste di autenticazione di base con il servizio URLFetch di App Engine (in Java)?Utilizzo di HTTP Basic-Auth con il servizio URLFetch di Google App Engine

Sembra posso impostare intestazioni HTTP:

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

Quali sono le intestazioni appropriate per Basic-Auth?

+1

Questa è davvero una domanda di App Engine, quindi? Basta cercare gli RFC HTTP per vedere come eseguire l'autenticazione di base (suggerimento - 'Autorizzazione'). –

+3

Speravo che potesse esserci un wrapper di convenienza per App Engine simile a Apache HttpClient in modo da non dover impostare manualmente (e codifica in base64) l'intestazione Autorizzazione. – Thilo

+0

informazioni molto utili –

risposta

30

Si tratta di un header di autenticazione di base su http:

Autorizzazione: Base64 codificato (nome utente: password)

esempio:

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

Sarà necessario fare questo:

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

E per fare che si vuole ottenere un api base64 codec, come il Apache Commons Codec

+1

Questo è quello che ho finito per fare. E poiché ho inserito username: password come proprietà in appengine-web.xml, ho appena inserito la versione codificata direttamente lì, quindi non ho nemmeno bisogno di un codec. (Puoi usare la linea di comando openssl: echo -n "username: password" | openssl enc -base64) – Thilo

+0

+1 questo risolve anche un problema che stavo per avere con l'autenticazione HTTP. Grazie. Oh, e getBytes() ha bisogno di un altro) per chiudere setRequestProperty. –

6

Si imposta un Authenticator prima di chiamare OpenConnection() in questo modo,

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

Poiché v'è un solo autenticatore predefinita globale, questo non funziona davvero bene quando si dispone di più utenti che fanno l'URLFetch in più thread. Vorrei usare Apache HttpClient se questo è il caso.

EDIT: Ho sbagliato. App Engine non consente l'autenticazione. Anche se consentito, avremmo il problema multi-thread con un'istanza di autenticazione globale. Anche se non puoi creare discussioni, le tue richieste potrebbero comunque essere pubblicate in thread diversi. Così abbiamo appena aggiungere l'intestazione manualmente utilizzando questa funzione,

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

C'è solo un singolo thread su App Engine ... (a proposito, c'è qualche documentazione che questo è garantito per essere il caso?) – Thilo

+0

Abbiamo avuto qualche problema con questo, ho pensato che fosse threading. Controllerò con la persona che l'ha implementata quando tornerò in ufficio la prossima settimana. –

+0

Ho appena parlato con il tizio che ha portato la nostra app su Google. Vedi le mie modifiche. –

1

Nota su la prima risposta: setRequestProperty dovrebbe ottenere il nome della proprietà senza i due punti ("Autorizzazione" piuttosto che "Autorizzazione:").

+0

Bella presa, ho modificato la risposta. –

14

Per chi è interessato a fare questo in Python (come mi è stato), il codice simile a questo:

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

Credo che il codice dovrebbe essere la seguente: risultato = urlfetch.fetch ( "http://yourserver.com/page/init.php, headers = { "Autorizzazione": "% s di base" base64% .encodestring ("username: password") [: - 1] }); –

+1

Da utilizzare: base64.encodestring ("nomeutente: password"). strip() –

+0

Aggiornato per utilizzare base64.b64encode. So che funziona perché è quello che stavo effettivamente usando nel mio codice reale –

4

Utilizzando HttpURLConnection mi ha dato qualche problema (per qualche motivo il server che stavo cercando di connettersi a didn 't accettare le credenziali auth), e alla fine ho capito che in realtà è molto più facile da fare usando API di basso livello URLFetch del GAE (com.google.appengine.api.urlfetch) in questo modo:

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

Questo ha funzionato.

+0

Questa dovrebbe essere la risposta accettata, puoi anche impostare il timeout: FetchOptions fetchOptions = FetchOptions.Builder.withDeadline (10); HTTPRequest req = new HTTPRequest (fetchurl, HTTPMethod.GET, fetchOptions); – ZiglioUK