如何在Unity 3d中使用Azure Notification Service

时间:2016-04-24 02:49:54

标签: azure encryption unity3d push-notification cryptography

我正在跨平台项目中工作,我们需要从Unity 3d连接到Azure Notification Hub。

我们正在尝试使用REST API,但我们遇到了生成SAS令牌的问题。当尝试写入流时,我们得到一个异常“错误写入请求:验证或解密失败。”

我认为SaS令牌的生成有问题,因为它必须被修改为跨平台并在Unity中工作。

这是迄今为止的代码

using UnityEngine;
using System.Collections;
using System;
using System.Net;
using System.IO;
using System.Text;
/// <summary>
/// check https://msdn.microsoft.com/en-us/library/azure/dn495627.aspx
/// check also http://piotrwalat.net/hmac-authentication-in-asp-net-web-api/
/// </summary>
public class AzureNotificationHub : MonoBehaviour
{
    public string CloudServiceNotificationHubPath = "cloudservicechat";
    public string CloudServiceNotificationHubConnectionString =
        "{CONNSTRINGHERE}";
    public string NotificationHubUrl = "{HUBURLHERE}";
    private ConnectionStringUtility objConnectionStringUtility = null;
    public string SasToken;

    public TextAsset CreateRegistrationTemplate = null;
    // Use this for initialization
    void Start()
    {
        this.objConnectionStringUtility = new ConnectionStringUtility(CloudServiceNotificationHubConnectionString);
        this.SasToken = this.objConnectionStringUtility.getSaSToken(this.NotificationHubUrl, 10);
    }

    // Update is called once per frame
    void Update()
    {

    }

    private string atomContentType = "application/atom+xml;type=entry;charset=utf-8";

    public void CreateRegistration()
    {
        string methodUrl = string.Format("{0}/{1}", this.NotificationHubUrl, "registrations/?api-version=2015-01");
        string result = HttpPost(methodUrl);
    }

    /// <summary>
    /// check http://stackoverflow.com/questions/9153181/adding-a-body-to-a-httpwebrequest-that-is-being-used-with-the-azure-service-mgmt
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    string HttpGet(string url)
    {
        HttpWebRequest req = WebRequest.Create(url)
                             as HttpWebRequest;
        req.Headers.Add("Content-Type", this.atomContentType);
        req.Headers.Add("Authorization", this.SasToken);
        req.Headers.Add("x-ms-version", "2015-01");
        req.Method = WebRequestMethods.Http.Get;
        string result = null;
        //writeStream.Write
        using (HttpWebResponse resp = req.GetResponse()
                                      as HttpWebResponse)
        {
            StreamReader reader =
                new StreamReader(resp.GetResponseStream());
            result = reader.ReadToEnd();
        }
        return result;
    }

    string HttpPost(string url)
    {
        string result = null;
        string tokenForUrl = this.objConnectionStringUtility.getSaSToken(url, 10);
        try
        {
            string body = this.CreateRegistrationTemplate.text;
            body = body.Replace("{tags}", string.Empty);
            body = body.Replace("{ChannelUri}", this.NotificationHubUrl);
            byte[] bodyArray = System.Text.Encoding.UTF8.GetBytes(body);

            HttpWebRequest req = WebRequest.Create(url)
                                 as HttpWebRequest;
            req.ContentType = this.atomContentType;
            //req.Headers.Add(HttpRequestHeader.Authorization, this.SasToken);
            req.Headers.Add(HttpRequestHeader.Authorization, tokenForUrl);
            req.Headers.Add("x-ms-version", "2015-01");
            req.Method = WebRequestMethods.Http.Post;
            Stream writeStream = req.GetRequestStream();
            writeStream.Write(bodyArray, 0, bodyArray.Length);
            writeStream.Flush();
            writeStream.Close();
            using (HttpWebResponse resp = req.GetResponse()
                                          as HttpWebResponse)
            {
                StreamReader reader =
                    new StreamReader(resp.GetResponseStream());
                result = reader.ReadToEnd();
            }
        }
        catch (Exception ex)
        {
            result = ex.Message;
        }
        return result;
    }

}

public partial class ConnectionStringUtility
{
    public string Endpoint { get; private set; }
    public string SasKeyName { get; private set; }
    public string SasKeyValue { get; private set; }
    private string sasTokenn { get; set; }

    public ConnectionStringUtility(string connectionString)
    {
        //Parse Connectionstring
        char[] separator = { ';' };
        string[] parts = connectionString.Split(separator);
        for (int i = 0; i < parts.Length; i++)
        {
            if (parts[i].StartsWith("Endpoint"))
                Endpoint = "https" + parts[i].Substring(11);
            if (parts[i].StartsWith("SharedAccessKeyName"))
                SasKeyName = parts[i].Substring(20);
            if (parts[i].StartsWith("SharedAccessKey"))
                SasKeyValue = parts[i].Substring(16);
        }
    }

    /// <summary>
    /// check http://buchananweb.co.uk/security01i.aspx
    /// </summary>
    /// <param name="uri"></param>
    /// <param name="minUntilExpire"></param>
    /// <returns></returns>
    public string getSaSToken(string uri, int minUntilExpire)
    {
        string targetUri = Uri.EscapeDataString(uri.ToLower()).ToLower();

        // Add an expiration in seconds to it.
        long expiresOnDate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
        expiresOnDate += minUntilExpire * 60 * 1000;
        long expires_seconds = expiresOnDate / 1000;
        String toSign = targetUri + "\n" + expires_seconds;

        HmacSignatureCalculator hmacSigner = new HmacSignatureCalculator();
        System.Security.Cryptography.SHA256Managed crypto = new System.Security.Cryptography.SHA256Managed();
        System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();

        var messageBuffer = ConvertStringToBinary(toSign, encoding);
        var keyBuffer = ConvertStringToBinary(SasKeyValue, encoding);

        var hmacKey = CreateKey(keyBuffer);
        var signedMessage = Sign(hmacKey, messageBuffer);

        string signature = Uri.EscapeDataString(signedMessage);

        return "SharedAccessSignature sr=" + targetUri + "&sig=" + signature + "&se=" + expires_seconds + "&skn=" + SasKeyName;
    }

    private byte[] CreateKey(byte[] keyBuffer)
    {
        System.Security.Cryptography.SHA256Managed crypto = new System.Security.Cryptography.SHA256Managed();
        var computedHash = crypto.ComputeHash(keyBuffer);
        return computedHash;

    }

    public string Sign(byte[] hmacKey, byte[] messageBuffer)
    {
        using (System.Security.Cryptography.SHA256Managed crypto = new System.Security.Cryptography.SHA256Managed())
        {
            var hash = crypto.ComputeHash(hmacKey);
            var signature = Convert.ToBase64String(hash);
            return signature;
        }
    }

    public byte[] ConvertStringToBinary(string value, Encoding encoding)
    {
        //Requires.NotNull(value, "value");
        //Requires.NotNull(encoding, "encoding");

        return encoding.GetBytes(value);
    }    
}

我应该做些什么? 谢谢你的帮助。

0 个答案:

没有答案