我正在尝试从Google云存储中获取可恢复的已签名上传网址,但我收到了无效的政策文件错误。下面是我正在使用的代码。我在这里做错了什么这里uploadUrl()是返回最终url的那个。我发布到该网址,希望从 GCS 获取位置URI,以便我可以 PUT 我的图片,但是我得到这个错误。
// Google Service Account Client ID. Replace with your account.
@Value("${google_cloud_storage.client_account}")
private String clientAccount;
// Private key from the private_key field in the download JSON file. Replace
// this!
@Value("${google_cloud_storage.private_key}")
private String private_key;
// base url of google cloud storage objects
static final String BASE_GCS_URL = "https://storage.googleapis.com";
// bucket and object we are trying to access. Replace this!
static final String OBJECT_PATH = "/XXX.appspot.com/public/images/new.jpg";
// full url to the object.
static final String FULL_OBJECT_URL = BASE_GCS_URL + OBJECT_PATH;
public String uploadUrl() throws Exception {
// expiry time of the url in Linux epoch form (seconds since january 1970)
String expiryTime;
// Set Url expiry to one minute from now!
expiryTime = setExpiryTimeInEpoch();
String stringToSign = getSignInput(expiryTime);
PrivateKey pk = getPrivateKey();
String signedString = getSignedWithSHA256(stringToSign, pk);
// URL encode the signed string so that we can add this URL
signedString = URLEncoder.encode(signedString, "UTF-8");
String signedUrl = getSignedUrl(signedString, expiryTime);
return signedUrl;
}
// Set an expiry date for the signed url. Sets it at one minute ahead of
// current time.
// Represented as the epoch time (seconds since 1st January 1970)
private String setExpiryTimeInEpoch() {
long now = System.currentTimeMillis();
// expire in a minute!
// note the conversion to seconds as needed by GCS.
long expiredTimeInSeconds = (now + 60 * 1000L) / 1000;
return expiredTimeInSeconds + "";
}
// The signed URL format as required by Google.
private String getSignedUrl(String signedString, String expiryTime) throws Exception {
String signedUrl = FULL_OBJECT_URL
+ "?GoogleAccessId=" + clientAccount
+ "&Expires=" + expiryTime
+ "&Policy=" + getPolicy()
+ "&Signature=" + signedString;
return signedUrl;
}
String getPolicy() throws Exception {
String fileName = "credentials/policy.json";
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
//File is found
System.out.println("File Found : " + file.exists());
//Read File Content
String content = "";
try {
content = new String(Files.readAllBytes(file.toPath()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Policy:" + content);
String encodedPolicy = Base64.getEncoder().encodeToString(content.getBytes());
String signedPolicy = getSignedWithSHA1(encodedPolicy);
String encodedSignedPolicy = Base64.getEncoder().encodeToString(signedPolicy.getBytes());
// URL encode the signed string so that we can add this URL
return encodedSignedPolicy;
}
// We sign the expiry time and bucket object path
private String getSignInput(String expiryTime) {
return "PUT" + "\n"
+ "image/jpg" + "\n"
+ "x-goog-resumable:start" + "\n"
+ expiryTime + "\n"
+ OBJECT_PATH;
}
private String getSignedWithSHA1(String input) throws Exception {
String sha1Str;
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
messageDigest.update(input.getBytes("UTF-8"));
sha1Str = byteArrayToString(messageDigest.digest());
} catch (Exception ignored) {
ignored.printStackTrace();
return null;
}
return Base64.getEncoder().encodeToString(sha1Str.getBytes());
}
public static String byteArrayToString(byte[] bytes) {
StringBuilder buffer = new StringBuilder();
for (byte b : bytes) {
buffer.append(String.format(Locale.getDefault(), "%02x", b));
}
return buffer.toString();
}
// Use SHA256withRSA to sign the request
private String getSignedWithSHA256(String input, PrivateKey pk) throws Exception {
Signature privateSignature = Signature.getInstance("SHA256withRSA");
privateSignature.initSign(pk);
privateSignature.update(input.getBytes("UTF-8"));
byte[] s = privateSignature.sign();
return Base64.getEncoder().encodeToString(s);
}
// Get private key object from unencrypted PKCS#8 file content
private PrivateKey getPrivateKey() throws Exception {
// Remove extra characters in private key.
String realPK = private_key.replaceAll("-----END PRIVATE KEY-----", "")
.replaceAll("-----BEGIN PRIVATE KEY-----", "").replaceAll("\n", "");
byte[] b1 = Base64.getDecoder().decode(realPK);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b1);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
由于