GAE Application needing to create Expiring Signed URL's to Google Cloud Storage

前端 未结 3 1982
半阙折子戏
半阙折子戏 2020-12-09 01:12

I was successfully able to create a stand-alone Java Application that creates Expiring Signed URL\'s to assets sitting in Google Cloud Storage. However, I have been unsucce

相关标签:
3条回答
  • 2020-12-09 01:26

    Two things:

    For googleAccessId use:

    String googleAccessId = service.getServiceAccountName();
    

    And for Signature use:

    SigningResult signingResult = service
                .signForApp(stringToSign.getBytes());
    String encodedSignature = new String(Base64.encodeBase64(
                signingResult.getSignature(), false), "UTF-8");
    

    That's what worked for me. See below a sample signer class:

    public class GcsAppIdentityServiceUrlSigner  {
    
        private static final int EXPIRATION_TIME = 5;
        private static final String BASE_URL = "https://storage.googleapis.com";
        private static final String BUCKET = "my_bucket";
        private static final String FOLDER = "folder";
    
    
        private final AppIdentityService identityService = AppIdentityServiceFactory.getAppIdentityService();
    
        public String getSignedUrl(final String httpVerb, final String fileName) throws Exception {
            final long expiration = expiration();
            final String unsigned = stringToSign(expiration, fileName, httpVerb);
            final String signature = sign(unsigned);
    
            return new StringBuilder(BASE_URL).append("/")
                    .append(BUCKET)
                    .append("/")
                    .append(FOLDER)
                    .append("/")
                    .append(fileName)
                    .append("?GoogleAccessId=")
                    .append(clientId())
                    .append("&Expires=")
                    .append(expiration)
                    .append("&Signature=")
                    .append(URLEncoder.encode(signature, "UTF-8")).toString();
        }
    
        private static long expiration() {
            final long unitMil = 1000l;
            final Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MINUTE, EXPIRATION_TIME);
            final long expiration = calendar.getTimeInMillis() / unitMil;
            return expiration;
        }
    
        private String stringToSign(final long expiration, String filename, String httpVerb) {
            final String contentType = "";
            final String contentMD5 = "";
            final String canonicalizedExtensionHeaders = "";
            final String canonicalizedResource = "/" + BUCKET + "/" + FOLDER + "/" + filename;
            final String stringToSign = httpVerb + "\n" + contentMD5 + "\n" + contentType + "\n"
                    + expiration + "\n" + canonicalizedExtensionHeaders + canonicalizedResource;
            return stringToSign;
        }
    
        protected String sign(final String stringToSign) throws UnsupportedEncodingException {
            final SigningResult signingResult = identityService
                    .signForApp(stringToSign.getBytes());
            final String encodedSignature = new String(Base64.encodeBase64(
                    signingResult.getSignature(), false), "UTF-8");
            return encodedSignature;
        }
    
        protected String clientId() {
            return identityService.getServiceAccountName();
        }
    }
    
    0 讨论(0)
  • 2020-12-09 01:26

    Using storage.cloud.google.com is requesting cookie based authenticated downloads. Changing:

    String baseURL = "https://storage.cloud.google.com/myproj/foo.txt"
    

    to

    String baseURL = "https://storage.googleapis.com/myproj/foo.txt"
    

    should work better.

    I'm not sure why you're only seeing this when using the URL created via App Engine. Maybe you're not logged in to Google when testing the App Engine application? Or running it in the local dev server?

    See the reference URIs section of the docs for details on possible request URIs.

    0 讨论(0)
  • 2020-12-09 01:29

    1/ Add the google api google-api-services-storage to your dependencies

    2/ Then you need to create ServiceAccountAuthCredentials object from your service account ID and primary key :

    serviceAccountAuthCredentials = AuthCredentials.createFor(resources.getString("authentication.p12.serviceAccountId"), pk);
    

    3/ Finally you generate the signed URL from the ServiceAccountAuthCredentials object and the bucket and file name (no need to generate a String to sign) :

    public String getSignedURL(String bucket, String fileName) throws IOException, GeneralSecurityException {
        BlobId blobId = BlobId.of(bucket, fileName);
        Blob blob = cloudStorageService.get(blobId);
        URL signedURL = blob.signUrl(durationSignedURLAvailable, TimeUnit.MINUTES, com.google.cloud.storage.Storage.SignUrlOption.signWith(serviceAccountAuthCredentials));
        return signedURL.toString();
    }
    

    This works fine for me.

    0 讨论(0)
提交回复
热议问题