Java Azure 请求签名 [英] Java Azure Request Signing

查看:27
本文介绍了Java Azure 请求签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是最新的 Azure SDK 存储模拟器.我正在尝试向我的 blob 签署请求.当我运行以下代码时,出现身份验证错误.

I am using the latest Azure SDK Storage emulator. I am trying to sign a request to my blob. When I run the below code I am getting auth error.

我不知道出了什么问题,尽管我已经多次检查代码是否符合 Azure SDK blob 访问规范.

I can't figure out what is wrong, although I have checked several times that the code conforms to the Azure SDK blob access specs.

这是控制台输出:

GET



x-ms-date:Sun, 23 Sep 2012 04:04:07 GMT
/devstoreaccount1/tweet/?comp=list
SharedKey devstoreaccount1:Hx3Pm9knGwCb4Hs9ftBX/+QlX0kCGGlUOX5g6JHZ9Kw=
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

代码如下:

public static void signRequest(HttpURLConnection request, String account, String key) 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";

    StringBuilder sb = new StringBuilder();
    sb.append("GET
"); // method
    sb.append('
'); // md5 (optional)
    sb.append('
'); // content type
    sb.append('
'); // legacy date
    sb.append("x-ms-date:" + date + '
'); // headers
    sb.append(request.getURL().getPath() + "/tweet/?comp=list"); // resource TODO: "?comp=..." if present

    System.out.println(sb.toString());
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(new SecretKeySpec(Base64.decode(key), "HmacSHA256"));
    String authKey = new String(Base64.encode(mac.doFinal(sb.toString().getBytes("UTF-8"))));
    String auth = "SharedKey " + account + ":" + authKey;
    request.setRequestProperty("x-ms-date", date);
    request.setRequestProperty("Authorization", auth);
    request.setRequestMethod("GET");
    System.out.println(auth);
}



public static void main(String args[]) throws Exception
{
     String account = "devstoreaccount1";
     String key = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
     HttpURLConnection connection = (HttpURLConnection) (new URL("http://localhost:10000/devstoreaccount1")).openConnection();
     signRequest(connection, account, key);
     connection.connect();
     System.out.println(connection.getResponseMessage());
 }

经过 Gaurav 和 Smarx 的反馈,这是代码,我仍然遇到相同的错误.你能告诉我一些代码吗?否则很难理解.

After feedback from Gaurav and Smarx, here is the code, I still get the same error. Can you show me some code? It is hard to understand otherwise.

    public static void sign(HttpURLConnection request, String account, String key, String url) 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";

        StringBuilder sb = new StringBuilder();
        sb.append("GET
"); // method
        sb.append('
'); // md5 (optional)
        sb.append('
'); // content type
        sb.append('
'); // legacy date
        sb.append("x-ms-date:" + date + '
'); // headers
        sb.append("x-ms-version:2009-09-19
"); // headers
        sb.append("/devstoreaccount1/devstoreaccount1/
$maxresults:1
comp:list
restype:container"); // resource TODO: "?comp=..." if present

        System.out.println(sb.toString());
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(Base64.decode(key), "HmacSHA256"));
        String authKey = new String(Base64.encode(mac.doFinal(sb.toString().getBytes("UTF-8"))));
        String auth = "SharedKeyLite " + account + ":" + authKey;
        request.setRequestProperty("x-ms-date", date);
        request.setRequestProperty("Authorization", auth);
        request.setRequestMethod("GET");
        System.out.println(auth);
    }

    public static void main(String args[]) throws Exception
    {

        String account = "devstoreaccount1";
        String key = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
        String url = "http://127.0.0.1:10000/devstoreaccount1/?restype=container&comp=list&$maxresults=1";
        HttpURLConnection connection = (HttpURLConnection) (new URL(url)).openConnection();
        sign(connection, account, key, url);
        connection.connect();
        System.out.println(connection.getResponseMessage());
    }

推荐答案

EDIT Gaurav 的回答到哪里去了?:-) 我相信他已经回答并提到您似乎正在构建 Shared Key Lite 签名,因此应该在您的授权标头中使用SharedKeyLite".

EDIT Where did Gaurav's answer go? :-) I believe he already answered and mentioned that you appear to be constructing a Shared Key Lite signature and should thus use "SharedKeyLite" in your authorization header.

我认为 Gaurav 的回答是正确的,但我注意到其他三个问题:

I think Gaurav is right in his answer, but I noticed three other issues:

  1. 您似乎正在调用 http://localhost/devstoreaccount1,但您正在计算 http://localhost/devstoreaccount1/tweet/?comp= 的签名列表.确保网址匹配.
  2. 对于存储模拟器,我认为您的规范化资源实际上应该是 /devstoreaccount1/devstoreaccount1/tweet/?comp=list.(注意账户名的重复.)一般应该是//,对于存储模拟器,账户名会出现在路径中.
  3. x-ms-version 标头在哪里?我相信这是必需的.
  1. You seem to be making a call to http://localhost/devstoreaccount1, but you're computing a signature for http://localhost/devstoreaccount1/tweet/?comp=list. Make sure the URLs match up.
  2. For the storage emulator, I think your canonicalized resource should actually be /devstoreaccount1/devstoreaccount1/tweet/?comp=list. (Note the repetition of the account name.) It should generally be /<account>/<path>, and for the storage emulator, the account name shows up in the path.
  3. Where's the x-ms-version header? I believe that's required.

更新 这是一些具有两种方法的工作代码,一种使用共享密钥,一种使用共享密钥精简版.希望这可以解决问题.请注意,要使用存储模拟器,您需要将 URL 切换回 localhost:10000/devstoreaccount1.签名代码应该仍然适用于模拟器,但我还没有测试过.Base64 库来自这里:http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html.

UPDATE Here's some working code with two methods, one that uses Shared Key and one that uses Shared Key Lite. Hopefully this clears things up. Note that to use the storage emulator, you'll want to switch the URL back to localhost:10000/devstoreaccount1. The signature code should still work for the emulator, but I haven't tested it. The Base64 library came from here: http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html.

import java.net.*;
import java.util.*;
import java.text.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import org.apache.commons.codec.binary.Base64;

public class Test
{
    private static Base64 base64 = new Base64();

    public static void signRequestSK(HttpURLConnection request, String account, String key) 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";

        StringBuilder sb = new StringBuilder();
        sb.append("GET
"); // method
        sb.append('
'); // content encoding
        sb.append('
'); // content language
        sb.append('
'); // content length
        sb.append('
'); // md5 (optional)
        sb.append('
'); // content type
        sb.append('
'); // legacy date
        sb.append('
'); // if-modified-since
        sb.append('
'); // if-match
        sb.append('
'); // if-none-match
        sb.append('
'); // if-unmodified-since
        sb.append('
'); // range
        sb.append("x-ms-date:" + date + '
'); // headers
        sb.append("x-ms-version:2009-09-19
");
        sb.append("/" + account + request.getURL().getPath() + "
comp:list");

        //System.out.println(sb.toString());
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(base64.decode(key), "HmacSHA256"));
        String authKey = new String(base64.encode(mac.doFinal(sb.toString().getBytes("UTF-8"))));
        String auth = "SharedKey " + account + ":" + authKey;
        request.setRequestProperty("x-ms-date", date);
        request.setRequestProperty("x-ms-version", "2009-09-19");
        request.setRequestProperty("Authorization", auth);
        request.setRequestMethod("GET");
        System.out.println(auth);
    }

    public static void signRequestSKL(HttpURLConnection request, String account, String key) 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";

        StringBuilder sb = new StringBuilder();
        sb.append("GET
"); // method
        sb.append('
'); // md5 (optional)
        sb.append('
'); // content type
        sb.append('
'); // legacy date
        sb.append("x-ms-date:" + date + '
'); // headers
        sb.append("x-ms-version:2009-09-19
");
        sb.append("/" + account + request.getURL().getPath() + "?comp=list");

        //System.out.println(sb.toString());
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(base64.decode(key), "HmacSHA256"));
        String authKey = new String(base64.encode(mac.doFinal(sb.toString().getBytes("UTF-8"))));
        String auth = "SharedKeyLite " + account + ":" + authKey;
        request.setRequestProperty("x-ms-date", date);
        request.setRequestProperty("x-ms-version", "2009-09-19");
        request.setRequestProperty("Authorization", auth);
        request.setRequestMethod("GET");
        System.out.println(auth);
    }



    public static void main(String args[]) throws Exception
    {
        String account = args[0];
        String key = args[1];
        HttpURLConnection connection = (HttpURLConnection) (new URL("http://" + account + ".blob.core.windows.net/?comp=list")).openConnection();
        signRequestSKL(connection, account, key);
        connection.connect();
        System.out.println(connection.getResponseMessage());

        connection = (HttpURLConnection) (new URL("http://" + account + ".blob.core.windows.net/?comp=list")).openConnection();
        signRequestSK(connection, account, key);
        connection.connect();
        System.out.println(connection.getResponseMessage());
    }
}

这篇关于Java Azure 请求签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆