尝试为存储桶资源生成签名URL时,我收到了SignatureDoesNotMatch错误。我已经查看了GCP github项目中的示例,并查看了其他帖子中的代码来调整我的内容,但我仍然不知道如何签署我的数据。
错误回复:
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.
</Message>
<StringToSign>
GET 2944813518 /bucketName/file.mp3
</StringToSign>
</Error>
代码
public String getSignedURL(String objectName, String contentType){
long timeStamp = System.currentTimeMillis() / 1000L;
timeStamp = timeStamp + (3600 * 24 * 365 * 1000);
String dataToBeSigned = "GET\n" + contentType +"\n" + timeStamp + "\n" + "/" + settings.getStorageBucketName() + "/" + objectName;
System.out.println(dataToBeSigned);
String signature = signData(dataToBeSigned);
String urlEncodedSignature = URLEncoder.encode(signature, "UTF-8");
return new StringBuilder("https://storage.googleapis.com")
.append("/")
.append(settings.getStorageBucketName())
.append("/")
.append(objectName)
.append("?GoogleAccessId=")
.append(settings.getStorageServiceAccountId())
.append("&Expires=")
.append(timeStamp)
.append("&Signature=")
.append(urlEncodedSignature).toString();
}
private String signData(String dataToBeSigned) {
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(getPrivateKey());
signer.update(dataToBeSigned.getBytes("UTF-8"));
byte[] rawSignature = signer.sign();
String base64EncodedSignature = new String(Base64.encodeBase64(rawSignature,false),"UTF-8");
return base64EncodedSignature;
}
private PrivateKey getPrivateKey() {
InputStream inputStream = new FileInputStream(settings.getStorageAccessKeyLocation());
String password = settings.getStorageAccessKeyPassword();
return SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), inputStream, password, "privatekey", password);
}
答案 0 :(得分:0)
spring-cloud-gcp-starter-storage
要与GCP集成,请在application.yml中定义属性:
spring:
cloud:
gcp:
project-id: PROJECT_ID
credentials:
location: classpath:GCP_SERVICE_ACCOUNT_KEY.json
@Autowired
private Storage storage;
public String getSignedUrlToWinReleasesBucketViaSdk() {
GoogleStorageResource googleStorageResource = new GoogleStorageResource(storage, "gs://BUCKET_NAME");
URL signedUrl = googleStorageResource.getBucket().get("OBJECT_NAME")
.signUrl(15, TimeUnit.MINUTES);
return signedUrl.toString();
}
public String getSignedUrlToWinReleasesBucket(String bucketName, String objectName) {
String expirationTime = nowPlusMinutes(15);
String urlTemplate = "GET" + "\n"
+ "" + "\n"
+ "" + "\n"
+ expirationTime + "\n"
+ "/" + bucketName + "/" + objectName;
String signature = getSignedString(urlTemplate, privateKey());
// URL encode the signed string so that we can add this URL
signature = URLEncoder.encode(signature, StandardCharsets.UTF_8);
String signedUrl = baseStorageUrl + "/" + bucketName + "/" + objectName
+ "?GoogleAccessId=" + gcpStorageClientEmail
+ "&Expires=" + expirationTime
+ "&Signature=" + signature;
return signedUrl;
}
private static String nowPlusMinutes(int minutes) {
long now = System.currentTimeMillis();
long expiredTimeInSeconds = (now + 60 * 1000L * minutes) / 1000;
return String.valueOf(expiredTimeInSeconds);
}
private static String getSignedString(String input, PrivateKey privateKey) {
try {
Signature privateSignature = Signature.getInstance("SHA256withRSA");
privateSignature.initSign(privateKey);
privateSignature.update(input.getBytes(StandardCharsets.UTF_8));
byte[] s = privateSignature.sign();
return Base64.encodeBase64String(s);
} catch (GeneralSecurityException e) {
throw new Exception("Cannot sign url with GCP Storage private key.", e, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
private PrivateKey privateKey() {
String key = gcpStoragePrivateKey
.replaceAll("-----END PRIVATE KEY-----", "")
.replaceAll("-----BEGIN PRIVATE KEY-----", "")
.replaceAll("\n", "");
byte[] keyDecoded = Base64.decodeBase64(key);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyDecoded);
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(spec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new Exception("Cannot get GCP Storage private key.", e, HttpStatus.INTERNAL_SERVER_ERROR);
}
}