简体   繁体   中英

generate public link for Google Cloud Storage objects

如何为用户通过BlobStore API提交的Google Cloud Storage对象生成公共链接?

There are a few ways to serve public GCS objects. One is signed URLs. Another is the getServingUrl() App Engine method.

However, if the object should be visible to everyone, you can do something simpler. Set the object's permissions to grant READ permission to "AllUsers", which allows the object to be read without any authentication, then simply refer users to this path:

https://storage.googleapis.com/BUCKET_NAME/OBJECT_NAME

That's it!

You can set an object to be publicly readable from the cloud console, via the APIs, or with this gsutil command: gsutil acl ch -g AllUsers:R gs://BUCKET_NAME/OBJECT_NAME

How to generate public link for Google Cloud Storage objects?

  1. Create a service account manually via the console and generate a .p12 key file.
  2. After the user uploads the file to the URL that was generated using:
blobstoreService.createUploadUrl("/fileUploadingHandler", 
        UploadOptions.Builder.withMaxUploadSizeBytes(1024*1024*10) // 10 MB max
                             .googleStorageBucketName(BUCKET_NAME));

the servlet (that handles /fileUploadingHandler ) can retrieve the file name of the GCS object and generate a temporary signed public link as follows:

Map<String, List<FileInfo>> fileInfoMap = blobstoreService.getFileInfos(request);
List<FileInfo> fileInfos = fileInfoMap.get("fileName");
FileInfo fileInfo = fileInfos.get(0);
String[] parts = fileInfo.getGsObjectName().split("/"); // get rid of /gs/buck_name/
String fileName = parts[parts.length - 1];
String signedUrl = GcsUrlSigner.generateSignedUrl(fileName);
// send the temporary public link (signedUrl) back to the user
import com.google.api.client.util.Base64;

import java.io.InputStream;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;

/**
 * Created by Fouad on 22-Dec-15.
 */
public class GcsUrlSigner
{
    private static final String DEFAULT_BUCKET_NAME = "XXXXXXXX.appspot.com";
    private static final String PUBLIC_URL_SERVICE_ACCOUNT_EMAIL = "XXXXXXXX@XXXXXX.iam.gserviceaccount.com";
    private static final String PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PATH = "XXXXXX.p12"; // located in the same folder as GcsUrlSigner.java
    private static final String PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PASSWORD = "notasecret";
    private static final long PUBLIC_URL_EXPIRATION_SECONDS = System.currentTimeMillis() / 1000 + 60; // 60 seconds

    public static String generateSignedUrl(String objectName) throws Exception
    {
        return generateSignedUrl(DEFAULT_BUCKET_NAME, objectName);
    }

    public static String generateSignedUrl(String bucketName, String objectName) throws Exception
    {
        PrivateKey key = loadKeyFromPkcs12(PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PATH, PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PASSWORD.toCharArray());
        return getSigningURL(key, "GET", PUBLIC_URL_EXPIRATION_SECONDS, bucketName, objectName);
    }

    private static String getSigningURL(PrivateKey key, String verb, long expirationSeconds, String bucketName, String objectName) throws Exception
    {
        String url_signature = signString(key, verb + "\n\n\n" + expirationSeconds + "\n" + "/" + bucketName + "/" + objectName);
        String signed_url = "https://storage.googleapis.com/" + bucketName + "/" + objectName +
                "?GoogleAccessId=" + PUBLIC_URL_SERVICE_ACCOUNT_EMAIL +
                "&Expires=" + expirationMillis +
                "&Signature=" + URLEncoder.encode(url_signature, "UTF-8");
        return signed_url;
    }

    private static PrivateKey loadKeyFromPkcs12(String filename, char[] password) throws Exception
    {
        InputStream is = GcsUrlSigner.class.getResourceAsStream(PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PATH);
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(is, password);
        return (PrivateKey) ks.getKey("privatekey", password);
    }

    private static String signString(PrivateKey key, String stringToSign) throws Exception
    {
        if(key == null) throw new Exception("Private Key not initalized");

        Signature signer = Signature.getInstance("SHA256withRSA");
        signer.initSign(key);
        signer.update(stringToSign.getBytes("UTF-8"));

        byte[] rawSignature = signer.sign();

        return new String(Base64.encodeBase64(rawSignature), "UTF-8");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM