简体   繁体   English

ASP.NET Web API登录方法

[英]ASP.NET Web API Login method

I'm wanting to build a RESTful web service using ASP.NET Web API that third-party developers will use to access my application's data. 我想使用ASP.NET Web API构建RESTful Web服务,第三方开发人员将使用它来访问我的应用程序的数据。

In Visual Studio I decided to create a new ASP.NET project. 在Visual Studio中,我决定创建一个新的ASP.NET项目。 I followed this tutorial but I choose a different template: Web API template. 我按照本教程,但我选择了另一个模板:Web API模板。 I use a MySQL database with the standard user role tables as explained in the tutorial. 我使用MySQL数据库和标准用户角色表,如教程中所述。

The template come with many very interesting methods to register a new user but there is no default Login request. 该模板带有许多非常有趣的方法来注册新用户,但没有默认的登录请求。 I wrote this without understanding what I'm doing: 我在不理解我在做什么的情况下写了这篇文章:

    // POST api/Account/Login
    [Route("Login")]
    public IHttpActionResult Login(LoginBindingModel model)
    {
        ClaimsIdentity ci = new ClaimsIdentity();
        // ...
        // ...
        Authentication.SignIn(ci);
        return Ok();
    }

I've read quite a lot about security without finding a good sample with documentation explaining how it works. 我已经阅读了很多关于安全性的文章而没有找到一个很好的样本,文档解释了它的工作原理。 It seems to be incredibly difficult to implement a simple login method in Web API. 在Web API中实现简单的登录方法似乎非常困难。

Could you explain me why there is no login method in this template. 你能解释一下为什么这个模板中没有登录方法吗? Do you have an sample of login method. 你有一个登录方法的样本。 And what should I sent back to the client application to authenticate the request. 我应该将哪些内容发送回客户端应用程序以验证请求。 Is this working with a token ? 这是使用令牌吗?

Usually what you do is implement the login logic in that method, and return a token which will be then validated on each call to your api. 通常你所做的是在该方法中实现登录逻辑,并返回一个令牌,然后在每次调用api时验证该令牌。

You can read this for more information 您可以阅读此内容以获取更多信息

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

If you have created a new ASP.NET Web Application -> Web API -> Change Authentication -> Individual User Accounts . 如果您已创建新的ASP.NET Web Application - > Web API - >更改身份验证 - > Individual User Accounts Have a look at App_Start -> Startup.Auth.cs . 看看App_Start - > Startup.Auth.cs

It should contain something like this: 它应该包含这样的东西:

PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    // In production mode set AllowInsecureHttp = false
    AllowInsecureHttp = true
};

// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);

This means that you can send a request for an access token, example request: 这意味着您可以发送访问令牌请求,示例请求:

在此输入图像描述

You can then verify that the access token works: 然后,您可以验证访问令牌是否有效:

在此输入图像描述

With this token you can now access all protected resources that the user has access to. 使用此令牌,您现在可以访问用户有权访问的所有受保护资源。

If you are going to build an API for third party developers then you need to secure it using OAuth 2.0 flows, I've written detailed post as @dariogriffo directed you which implements the resource owner password credentials flow which good for your case. 如果您要为第三方开发人员构建API,那么您需要使用OAuth 2.0流程来保护它,我已经编写了详细的帖子,因为@dariogriffo指示您实现资源所有者密码凭据流,这对您的情况很有用。

You do not need to create an end point for login, you will configure the API using Owin middle-wares to issue OAuth bearer tokens to the users when calling an end point such as "/token", and then the users keep sending this token along with each request in the Authorization header. 您无需为登录创建终点,您将使用Owin中间件配置API,以便在调用端点(例如“/ token”)时向用户发出OAuth承载令牌,然后用户继续发送此令牌以及Authorization标头中的每个请求。 Read more about this token based authentication . 详细了解基于令牌的身份验证

For Others, a helper class, to begin with: 对于Others,帮助类,首先是:

namespace WeBAPITest
{



#region Using Statements:



using System.Net.Http;
using System.Collections.Generic;

using Newtonsoft.Json;



#endregion



public class HttpWebApi
{



#region Fields:



private static readonly HttpClient client = new HttpClient();



#endregion



#region Properties:



/// <summary>
/// The basr Uri.
/// </summary>
public string BaseUrl { get; set; }



/// <summary>
/// Username.
/// </summary>
protected internal string Username { get; set; }



/// <summary>
/// Password.
/// </summary>
protected internal string Password { get; set; }



/// <summary>
/// The instance of the Root Object Json Deserialised Class.
/// </summary>
internal Rootobject Authentication { get; set; }



/// <summary>
/// The Access Token from the Json Deserialised Login.
/// </summary>
public string AccessToken { get { return Authentication.access_token; } }



#endregion



public HttpWebApi(string baseurl)
{

    // Init Base Url:
    BaseUrl = baseurl;
}



/// <summary>
/// Get from the Web API.
/// </summary>
/// <param name="path">The BaseUrl + path (Uri.Host + api/Controller) to the Web API.</param>
/// <returns>A Task, when awaited, a string</returns>
public async System.Threading.Tasks.Task<string> Get(string path)
{

    if (Authentication.access_token == null)
    throw new System.Exception("Authentication is not completed.");

    // GET
    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Authentication.access_token);
    return await client.GetStringAsync(BaseUrl + path);
}



/// <summary>
/// Logs In and populates the Authentication Variables.
/// </summary>
/// <param name="username">Your Username</param>
/// <param name="password">Your Password</param>
/// <returns>A Task, when awaited, a string</returns>
public async System.Threading.Tasks.Task<string> Login(string username, string password)
{

    // Set Username:
    Username = username;

    // Set Password:
    Password = password;

    // Conf String to Post:
    var Dic = new Dictionary<string, string>() { { "grant_type", "password" }, { "username", "" }, { "password", "" } };
    Dic["username"] = username;
    Dic["password"] = password;

    // Post to Controller:
    string auth = await Post("/Token", Dic);

    // Deserialise Response:
    Authentication = JsonConvert.DeserializeObject<Rootobject>(auth);

    return auth;
}



/// <summary>
/// Post to the Web API.
/// </summary>
/// <param name="path">The BaseUrl + path (Uri.Host + api/Controller) to the Web API.</param>
/// <param name="values">The new Dictionary<string, string> { { "value1", "x" }, { "value2", "y" } }</param>
/// <returns>A Task, when awaited, a string</returns>
public async System.Threading.Tasks.Task<string> Post(string path, Dictionary<string, string> values)
{

    // Add Access Token to the Headder:
    if (Authentication != null)
    if (Authentication.access_token != "")
        client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Authentication.access_token);

    // Encode Values:
    var content = new FormUrlEncodedContent(values);

    // Post and get Response:
    var response = await client.PostAsync(BaseUrl + path, content);

    // Return Response:
    return await response.Content.ReadAsStringAsync();
}



/// <summary>
/// Register a new User.
/// </summary>
/// <param name="username">Your Username, E-Mail</param>
/// <param name="password">Your Password</param>
/// <returns>A Task, when awaited, a string</returns>
public async System.Threading.Tasks.Task<string> Register(string username, string password)
{

    // Register: api/Account/Register
    var Dic = new Dictionary<string, string>() { { "Email", "" }, { "Password", "" }, { "ConfirmPassword", "" } };
    Dic["Email"] = username;
    Dic["Password"] = password;
    Dic["ConfirmPassword"] = password;

    return await Post("api/Account/Register", Dic);
}
}



/// <summary>
/// For Json Deserialisation.
/// </summary>
internal class Rootobject
{

/// <summary>
/// The Web Api Access Token. Gets added to the Header in each communication.
/// </summary>
public string access_token { get; set; }



/// <summary>
/// The Token Type
/// </summary>
public string token_type { get; set; }



/// <summary>
/// Expiry.
/// </summary>
public int expires_in { get; set; }



/// <summary>
/// The Username.
/// </summary>
public string userName { get; set; }



/// <summary>
/// Issued.
/// </summary>
public string issued { get; set; }



/// <summary>
/// Expiry.
/// </summary>
public string expires { get; set; }
}
}

Particularly designed for the default, unedited Web Api Template in Visual Studio. 特别为Visual Studio中的默认未经编辑的Web Api模板而设计。

Then: 然后:

HttpWebApi httpWebApi = new HttpWebApi("http://localhost/");
await httpWebApi.Login("email", "password");

richTextBox1.AppendText(await httpWebApi.Get("api/Account/UserInfo") + Environment.NewLine);

Hope this helps others some! 希望这有助于其他人!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM