问题
I am using java to make a REST Api call to Azure, put an object to its storage. I did this successfully last week but now its now working for some reasons. The error message is as below:
<?xml version="1.0" encoding="utf-8" ?>
<Error>
<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:a15f2626-0001-004f-778c-f34383000000 Time:2017-07-02T23:43:20.2826278Z</Message>
<AuthenticationErrorDetail>The Date header in the request is incorrect.</AuthenticationErrorDetail>
</Error>
I don't think this is caused by the incorrect time stamp because the "Date" field and the response time are within 15 minutes. The "Date" field in the header is Sun, 2 Jul 2017 23:38:04 GMT Here are my java code to generate the token and send the request.
public void putObject(String blobName) {
try {
URL restServiceURL = new URL(getCallAddress() + "/" + blobName);
HttpURLConnection httpConnection = (HttpURLConnection) restServiceURL.openConnection();
Calendar cd = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = sdf.format(cd.getTime());
httpConnection.setDoInput(true);
httpConnection.setDoOutput(true);
try {
httpConnection.setRequestMethod("PUT");
} catch (ProtocolException e) {
e.printStackTrace();
}
httpConnection.setFixedLengthStreamingMode(getFile().length()); //set output size to avoid out of memory error
try {
String token = createToken(blobName, date);
httpURLConnection.setRequestProperty("Authorization", "SharedKey " + Azure_AccountName + ":" + token);
} catch (Exception e) {
log.error("Cannot get token");
e.printStackTrace();
}
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(getFile().length()));
httpURLConnection.setRequestProperty("x-ms-blob-type", "BlockBlob");
httpURLConnection.setRequestProperty("x-ms-version", "2015-12-11");
httpURLConnection.setRequestProperty("x-ms-date",date);
} catch (IOException e) {
log.error(e);
e.printStackTrace();
}
FileInputStream inputStream = new FileInputStream(getFile());
try {
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
OutputStream out = httpConnection.getOutputStream();
out.write(buffer);
out.flush();
out.close();
int code = httpConnection.getResponseCode();
if (code != 201 && code != 200) {
log.error(code + httpConnection.getResponseMessage());
throw new UnsupportedOperationException("Put object failed");
}
httpConnection.disconnect();
} catch (Exception e) {
log.error(e);
e.printStackTrace();
} finally {
IOUtils.closeQuietly(inputStream);
}
}
private String createToken(String blobName, String date) throws InvalidKeyException, NoSuchAlgorithmException,
UnsupportedEncodingException {
String signature = "PUT\n\n\n" + getFile().length() + "\n\n\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:" + date +
"\nx-ms-version:2015-12-11\n" + "/" + Azure_AccountName + "/" + Azure_BucketName + "/" + blobName;
SecretKey secreteKey = new SecretKeySpec(Base64.decode(KEY), "HmacSHA256");
Mac sha256HMAC = Mac.getInstance(secreteKey.getAlgorithm());
sha256HMAC.init(secreteKey);
byte[] digest = sha256HMAC.doFinal(signature.getBytes("UTF8"));
return new String(Base64.encode(digest));
}
回答1:
You could refer to the code below if you haven't solved this Authentication error:
public class PutTest {
private static final String account = <your account name>;
private static final String key = <your account key>;
public static void main(String args[]) throws Exception {
File file = new File(<your file path>);
FileInputStream inputStream = new FileInputStream(<your file path>);
String urlString = "https://" + account + ".blob.core.windows.net/<your container>/<your file name e.g:test.txt>";
HttpURLConnection connection = (HttpURLConnection) (new URL(urlString)).openConnection();
getFileRequest(connection, account, key, file.length());
// connection.connect();
connection.setDoInput(true);
connection.setDoOutput(true);
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
OutputStream out = connection.getOutputStream();
out.write(buffer);
out.flush();
out.close();
System.out.println("Response message : " + connection.getResponseMessage());
System.out.println("Response code : " + connection.getResponseCode());
BufferedReader br = null;
if (connection.getResponseCode() != 200) {
br = new BufferedReader(new InputStreamReader((connection.getErrorStream())));
} else {
br = new BufferedReader(new InputStreamReader((connection.getInputStream())));
}
System.out.println("Response body : " + br.readLine());
}
public static void getFileRequest(HttpURLConnection request, String account, String key, long length)
throws Exception {
SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = fmt.format(Calendar.getInstance().getTime()) + " GMT";
String stringToSign = "PUT\n" + "\n" // content encoding
+ "\n" // content language
+length+"\n"// content length
+ "\n" // content md5
+"\n" // content type
+ "\n" // date
+ "\n" // if modified since
+ "\n" // if match
+ "\n" // if none match
+ "\n" // if unmodified since
+ "\n" // range
+ "x-ms-blob-type:BlockBlob" + "\n"
+ "x-ms-date:" + date + "\n"
+ "x-ms-version:2015-02-21"+"\n" // headers
+ "/" + account + request.getURL().getPath(); // resources
System.out.println("stringToSign : " + stringToSign);
String auth = getAuthenticationString(stringToSign);
request.setRequestMethod("PUT");
request.setRequestProperty("x-ms-blob-type", "BlockBlob");
request.setRequestProperty("x-ms-date", date);
request.setRequestProperty("x-ms-version", "2015-02-21");
request.setRequestProperty("Authorization", auth);
request.setRequestProperty("Content-Length", String.valueOf(length));
}
private static String getAuthenticationString(String stringToSign) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(Base64.decode(key), "HmacSHA256"));
String authKey = new String(Base64.encode(mac.doFinal(stringToSign.getBytes("UTF-8"))));
String auth = "SharedKey " + account + ":" + authKey;
return auth;
}
}
Hope it helps.
来源:https://stackoverflow.com/questions/44891375/get-authentication-error-when-put-object-to-azure-storage