2016-06-09 5 views
1

Ich erstelle einen signedURL in einem Endpunkt der App Engine und versorge ihn dann mit dem Client. Aber wenn der Client zu laden versucht, die signierte URL, wirft der Cloud-Speicher wird folgender FehlerProblem beim Hochladen in den Google Cloud-Speicher unter Verwendung der signierten URL

Access denied. Anonymous users does not have storage.objects.create access to bucket

Den Code App Engine unterzeichnet URL zu erzeugen, ist wie folgt:

private String getSignedUrl() { 
String encodedUrl = null; 
String httpVerb = "PUT"; 
String contentMD5 = ""; 
String contentType = "image/rgb"; 

Calendar calendar = Calendar.getInstance(); 
calendar.add(Calendar.MINUTE, 10); 
long expiration = calendar.getTimeInMillis()/1000L; 
String canonicalizedExtensionHeaders = ""; 
String canonicalizedResource = 
    "/<bucket_name>/<folder_name>/"; 

String stringToSign = 
    httpVerb + "\n" + contentMD5 + "\n" + contentType + "\n" 
     + expiration + "\n" + canonicalizedExtensionHeaders 
     + canonicalizedResource; 

AppIdentityService service = 
    AppIdentityServiceFactory.getAppIdentityService(); 
String googleAccessId = service.getServiceAccountName(); 

String baseURL = 
    "http://storage.googleapis.com/<bucket_name>/<folder-name>/"; 
SigningResult signingResult = 
    service.signForApp(stringToSign.getBytes()); 
String encodedSignature = null; 
try { 
    encodedSignature = 
     URLEncoder.encode(
      new String(Base64.encodeBase64(
       signingResult.getSignature(), false), 
       "UTF-8"), "UTF-8").toString(); 
} catch (UnsupportedEncodingException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 
encodedUrl = 
    baseURL + "?GoogleAccessId=" + googleAccessId + "&Expires=" 
     + expiration + "&Signature=" + encodedSignature; 

return encodedUrl; 
} 

Und nach Erhalt die signierte URL, verwende ich cURL, um den Upload zu testen. Ich verwende den folgenden Befehl, um die Datei

curl -X PUT -H "Content-Type: multipart/form" -F [email protected]"<file_path>";type=image/rgb <signed_url> 

Ich habe versucht, beide POST habe hochladen und in der cURL mit dem gleichen Ergebnis PUT. Fehle ich hier etwas?

+0

Ich weiß nicht, ob dies das Problem ist, aber im Allgemeinen möchten Sie wahrscheinlich URLs für HTTPS statt HTTP signieren. –

+0

Auch mit https und nach dem Entfernen des Ordnernamens gemäß @Antrau Vorschlag kann ich nicht vom Client hochladen. –

Antwort

1

Schreiben aus dem Speicher hier, aber ich denke, dass Sie den Objektnamen angeben müssen. Außerdem haben Sie den Ordnernamen in baseURL aufgenommen - nur der Bucket-Name sollte enthalten sein. Der Name "Ordner" ist Teil des Objektnamens.

+0

Ich möchte tatsächlich die signierte URL generieren, damit Kunden zu GCS hochladen können, ohne ein Google-Konto zu haben. Daher gibt es keinen Objektnamen in der Basis-URL. Wie Sie vorgeschlagen haben, habe ich den Ordnernamen aus der 'canonicalizedResource' und' baseURL' in meinem Code entfernt. Jetzt beobachte ich die folgende Fehlerantwort 'MissingSecurityHeader Ihre Anfrage fehlte eine erforderliche Kopfzeile.

Autorisierung
' –

+0

Können Sie den Client überprüfen, um sicherzustellen, dass er die URL-Abfrageparameter sendet? Das klingt wie die Art von etwas, das passieren würde, wenn es den Signature-Parameter auf dem Weg streifte. Eine andere Sache, die einen Versuch wert ist, ist, dem Client eine bekannte gut signierte URL zu geben, um zu sehen, ob es funktioniert. Das Dienstprogramm gsutil kann sie für Sie generieren. –

+0

@SudarshanMurthy: Der Workflow lautet wie folgt: Bitten Sie einen Benutzer, eine Datei zum Hochladen auszuwählen, den Namen der Datei abzurufen, eine signierte URL vom Backend anzufordern, diese URL auf Ihr Datei-Upload-Formular zu setzen und das Datei-Upload-Formular zu senden. –

0

Sie haben auch zu URL kodieren googleAccessId und encodedSignature wegen der @ Zeichen in das Dienstkonto E-Mail und eine Base64-codierte Zeichenfolge kann den + Charakter haben, die als ein Raum durch den Server decodiert wird.