使用 ASP.NET MVC 身份作为后端的 Xamarin 身份验证和令牌

Xamarin auth and tokens using ASP.NET MVC identity as backend

所以我使用本教程设置了一个 ASP.NET 具有身份和 Oauth2 的 MVC 应用程序:

http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/

如果你想这样做,我怎么推荐那个教程都不够,它非常棒。我现在可以通过以下 HTTP 请求使用存储在 MVC 数据库中的用户名/密码登录:

POST /token HTTP/1.1
Host: mymvcsite.azurewebsites.net
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
grant_type=password&username=MyUserName&password=MyPassword

我使用 javascript 作为使用 HttpRequest 的概念证明,它工作得非常好。我得到了令牌和一切。我的回复如下所示:

{
    "access_token": "A Really long character string",
    "token_type": "bearer",
    "expires_in": 86399
}

所以目前一切都在 Xamarin 之外工作,现在我正在努力思考如何将所有这些插入我的 Xamarin 项目。我的第一个困惑来源是 Xamarin.auth 插件以及在这种情况下如何使用它(如果有的话)。我在这个插件上找不到任何不使用 Facebook 或 Google 作为身份验证提供者的东西,而且我正在做的事情似乎不适合您拥有客户端密码和 ClientID 等的模型.我想了解的第二件事是,一旦我拥有了令牌,我将如何处理它。这里的最终目标是在 MVC 站点中创建一些 Web 服务,让用户使用 oauth 对 MVC 身份进行身份验证,然后安全地访问这些 Web 服务。所以我的问题是:

1) 在这种情况下我会使用 Xamain.auth 吗?如果是这样,是否有任何好的资源可以举例说明我正在尝试做的事情?

2) 获得令牌后,如何保护 Web 服务以期待这样的 oauth2 令牌?

您在此处发布的资源很棒。我也使用过它,并且构建了一个完整的 (Xamarin) 可移植 class 库,可以在每个请求等时自动提交此令牌

在 ASP.NET MVC 中,只需添加

[Authorize]

-属性超过你的API-控制器。如果您正确遵循指南,这将立即保护它们。

保护您的 API 之后,您需要发送包含不记名令牌的请求。这就是我在我的项目中实现它的方式:

// First logging in and getting a token:
public async Task<bool> OAuthLoginAsync(string username, string password)
{
    var formContent = new FormUrlEncodedContent(new[]
    {
      new KeyValuePair<string, string>("username", username),
      new KeyValuePair<string, string>("password", password),
      new KeyValuePair<string, string>("grant_type", "password")
    });

    Token = await PostAndReadAsync<TokenResponse>(_oauthEndpointUri, formContent);

}
// this method is responsible for sending the request and returning an object
public async Task<T> PostAndReadAsync<T>(string path, HttpContent content)
    {
        var httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Add("Accept", "application/json");

        var responseMessage = await httpClient.PostAsync(path, content, cancellationToken);
        if (!responseMessage.IsSuccessStatusCode) {
          throw new Exception("Something went wrong...");
        }

        return await responseMessage.Content.ReadAsAsync<T>(cancellationToken);
      }
}

代币定义:

public class TokenResponse
  {
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

    [JsonProperty("token_type")]
    public string TokenType { get; set; }

    [JsonProperty("expires_in")]
    public int ExpiresIn { get; set; }

    [JsonProperty("refresh_token")]
    public string RefreshToken { get; set; }

    [JsonProperty("as:client_id")]
    public string ClientId { get; set; }

    [JsonProperty("userName")]
    public string UserName { get; set; }

    [JsonProperty(".issued")]
    public DateTime IssueDate { get; set; }

    [JsonProperty(".expires")]
    public DateTime ExpireDate { get; set; }
  }

然后在任何后续 api 调用中(您应该提供 oauth 令牌)您应该添加访问令牌。

HttpClient.DefaultRequestHeaders.Authorization = 
new AuthenticationHeaderValue("Bearer", Token.AccessToken);

作为一个额外的好处,前面指定的 PostAndReadAsync 方法可以重复用于调用任何其他资源(因为它 returns <T>)所以它是可重复使用的。

希望这对您(以及许多面临相同问题的其他人)有所帮助。如果您的情况不完整,请随时询问更多信息。

请注意,为简单起见,我删除了所有 try/catches 和取消令牌。

您的(共享)移动项目中需要以下 nuget 包:

Microsoft.Bcl
Microsoft.Bcl.Build
Microsoft.Bcl.Http
Microsoft.AspNet.WebApi.Client
Newtonsoft.Json