在Windows Azure移动服务中实施自定义身份验证

时间:2014-08-17 08:10:19

标签: azure-mobile-services

Windows Azure移动服务目前没有自定义身份验证选项并查看功能请求

http://feedback.azure.com/forums/216254-mobile-services/suggestions/3313778-custom-user-auth

它不会很快到来。

使用.NET后端和.NET应用程序,如何实现自定义身份验证,以便您不必使用Facebook,Google或其他任何当前提供商?

有很多部分完成的教程,介绍如何使用JS后端以及iOS和Android完成此操作,但.NET示例在哪里?

2 个答案:

答案 0 :(得分:20)

我终于完成了解决方案,在下面列出的文章的帮助下,一些智能感知和一些反复试验。

WAMS如何运作

首先,我想以一种非常简单的形式描述WAMS是什么,因为这部分让我困惑了一段时间,直到它最终点击。 WAMS只是为了快速部署而打包的预先存在的技术的集合。您需要了解的情况是:

enter image description here

正如您所看到的,WAMS实际上只是WebAPI和其他东西的容器,我在这里不会详细介绍。在Azure中创建新的移动服务时,您可以下载包含WebAPI的项目。他们使用的示例是TodoItem,因此您将通过项目看到此场景的代码。

下面是您从(我刚刚开始使用Windows Phone 8应用程序)下载此示例的地方

enter image description here

我可以继续讨论这个问题,但本教程将帮助您入门:

  

http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-windows-store-dotnet-get-started/

设置WAMS项目

您需要MasterKey和ApplicationKey。您可以从Azure门户获取它们,单击您的移动服务应用程序并按下底部的管理密钥

enter image description here

你刚下载的项目,在Controllers文件夹中我刚刚创建了一个名为AccountController.cs的新控制器,我在里面放了

    public HttpResponseMessage GetLogin(String username, String password)
    {
        String masterKey = "[enter your master key here]";
        bool isValidated = true;

        if (isValidated)
            return new HttpResponseMessage() { StatusCode = HttpStatusCode.OK, Content = new StringContent("{ 'UserId' : 'F907F58C-09FE-4F25-A26B-3248CD30F835', 'token' : '" + GetSecurityToken(new TimeSpan(1,0, 0), String.Empty, "F907F58C-09FE-4F25-A26B-3248CD30F835", masterKey)  + "' }") };
        else
            return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Username and password are incorrect");

    }

    private static string GetSecurityToken(TimeSpan periodBeforeExpires, string aud, string userId, string masterKey)
    {
        var now = DateTime.UtcNow;
        var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
        var payload = new
        {
            exp = (int)now.Add(periodBeforeExpires).Subtract(utc0).TotalSeconds,
            iss = "urn:microsoft:windows-azure:zumo",
            ver = 2,
            aud = "urn:microsoft:windows-azure:zumo",
            uid = userId
        };

        var keyBytes = Encoding.UTF8.GetBytes(masterKey + "JWTSig");
        var segments = new List<string>();

        //kid changed to a string
        var header = new { alg = "HS256", typ = "JWT", kid = "0" };
        byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None));
        byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None));
        segments.Add(Base64UrlEncode(headerBytes));
        segments.Add(Base64UrlEncode(payloadBytes));
        var stringToSign = string.Join(".", segments.ToArray());
        var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
        SHA256Managed hash = new SHA256Managed();
        byte[] signingBytes = hash.ComputeHash(keyBytes);
        var sha = new HMACSHA256(signingBytes);
        byte[] signature = sha.ComputeHash(bytesToSign);
        segments.Add(Base64UrlEncode(signature));
        return string.Join(".", segments.ToArray());
    }

    // from JWT spec
    private static string Base64UrlEncode(byte[] input)
    {
        var output = Convert.ToBase64String(input);
        output = output.Split('=')[0]; // Remove any trailing '='s
        output = output.Replace('+', '-'); // 62nd char of encoding
        output = output.Replace('/', '_'); // 63rd char of encoding
        return output;
    }

您可以使用自己的验证码替换GetLogin中的内容。验证后,它将返回所需的安全令牌(JWT)。

如果您正在测试localhost,请记住进入您的web.config文件并填写以下密钥

<add key="MS_MasterKey" value="Overridden by portal settings" />
<add key="MS_ApplicationKey" value="Overridden by portal settings" />

您需要在此输入您的主密钥和应用密钥。当您上传它们时它们将被覆盖,但如果您在本地运行所有内容,则需要输入它们。

在TodoItemController的顶部添加AuthorizeLevel属性,如下所示

[AuthorizeLevel(AuthorizationLevel.User)]
public class TodoItemController : TableController<TodoItem>

您需要修改TodoItemController中的大多数功能,但这里是Get All功能的示例。

    public IQueryable<TodoItem> GetAllTodoItems()
    {
        var currentUser = User as ServiceUser;

        Guid id = new Guid(currentUser.Id);

        return Query().Where(todo => todo.UserId == id);
    }

只是旁注我使用UserId作为Guid(uniqueidentifier),你需要将它添加到todo模型定义中。您可以将UserId设置为您想要的任何类型,例如INT32

Windows Phone / Store应用

请注意,这只是一个示例,您应该在主应用程序运行后清理代码。

在您的客户端应用

安装NuGet包:Windows Azure移动服务

进入App.xaml.cs并将其添加到顶部

    public static MobileServiceClient MobileService = new MobileServiceClient(
          "http://localhost:50527/",
          "[enter application key here]"
    );

在我创建的MainPage.xaml.cs中

public class Token
{
    public Guid UserId { get; set; }
    public String token { get; set; }
}

在主类中添加一个Authenticate函数

    private bool Authenticate(String username, String password)
    {
        HttpClient client = new HttpClient();
        // Enter your own localhost settings here
        client.BaseAddress = new Uri("http://localhost:50527/");

        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        HttpResponseMessage response = client.GetAsync(String.Format("api/Account/Login?username={0}&password={1}", username, password)).Result;

        if (response.StatusCode == System.Net.HttpStatusCode.OK)
        {
            var token = Newtonsoft.Json.JsonConvert.DeserializeObject<Token>(response.Content.ReadAsStringAsync().Result);

            App.MobileService.CurrentUser = new MobileServiceUser(token.UserId.ToString());
            App.MobileService.CurrentUser.MobileServiceAuthenticationToken = token.token;

            return true;
        }
        else
        {
            //Something has gone wrong, handle it here
            return false;
        }           

    }

然后在Main_Loaded函数

    private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        Authenticate("test", "test");

        RefreshTodoItems();
    }

如果您在WebAPI中有断点,您将看到它进入,获取令牌,然后返回ToDoItemController,currentUser将填充UserId和令牌。

您需要创建自己的登录页面,因为此方法无法将自动创建的登录页面与其他身份提供程序一起使用。但是我更喜欢创建自己的登录屏幕。

任何其他问题都会在评论中告诉我,如果可以,我会帮助你。

安全提示

请记住使用SSL。

<强>参考

[] http://www.thejoyofcode.com/Exploring_custom_identity_in_Mobile_Services_Day_12_.aspx

[] http://www.contentmaster.com/azure/creating-a-jwt-token-to-access-windows-azure-mobile-services/

[] http://chrisrisner.com/Custom-Authentication-with-Azure-Mobile-Services-and-LensRocket

答案 1 :(得分:1)

这正是你如何做到的。这个男人需要10颗星和5箱啤酒!

有一件事,我使用移动服务LoginResult进行登录,如: var token = Newtonsoft.Json.JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync()。Result);

希望现在进入Android!