简体   繁体   English

了解 ASP.NET 中的令牌生成/验证(MVC、Web API)

[英]Understanding Token Generation/Validation in ASP.NET (MVC, web API)

I am developing a MVC project in which I am generating a token to authorize anyone who has it to say the famous "Hello World!".我正在开发一个 MVC 项目,我正在生成一个令牌来授权任何拥有它的人说著名的“Hello World!”。 Since I am a new one in ASP.NET I don't understand WHERE and WHO generates the token, and where (or how) is it saved once it is generated.由于我是 ASP.NET 中的新手,因此我不了解 WHERE 和 WHO 生成令牌的位置,以及生成后将其保存在何处(或如何)。 Also I don't know Who validates the token once I launch a Get/Post with the token.此外,一旦我使用令牌启动获取/发布,我也不知道谁会验证令牌。 The final purpose is to try to change the type of token generated, obtaining a new one like a JWT Token, instead of a Basic one.最终目的是尝试改变生成的令牌类型,获得一个像 JWT 令牌这样的新令牌,而不是基本令牌。 I'm using OWIN.我正在使用 OWIN。

Here are the parts I think important to undestand all.以下是我认为理解所有重要的部分。

using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;
using ExampleToUnderstand.Models;
using ExampleToUnderstand.Providers;

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
        var config = new HttpConfiguration();
        WebApiConfig.Register(config);
        app.UseWebApi(config);
    }
}

/*Following the partial class Startup.Auth.cs*/
public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
        var oAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            // AuthorizationCodeFormat = new JwtFormat(audienceId, new SymmetricKeyIssuerSecurityTokenProvider(issuer, signingKey)), // da togliere se non funziona
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(3),
            Provider = new AuthorizationProvider ()
        };
        // Token Generation
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }
}

Then I developed a provider, following some guides, and the result is this:然后我按照一些指南开发了一个提供程序,结果是这样的:

using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin.Security.OAuth;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Threading.Tasks;
 
public class AuthorizationProvider : OAuthAuthorizationServerProvider
{
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
        var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
        IdentityUser user = await userManager.FindAsync(context.UserName, context.Password);
        if (user == null)
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return;
        }
        
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
        identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
        context.Validated(identity);
    /*WHO GENERATES THE TOKEN HERE?? WHICH IS THE ALGHORITHM USED??*/
    }
}

Using Postman I obtain a result like this.使用 Postman 我得到了这样的结果。

{
  "access_token": "mxHZZEFB6pAc6WnTkjeamyxgDMUVNy64CkmtTEwwN2yLZkDQkfDy3J6EIVVLDNRN1-XkeA50Xqk0oB9DEprEuCzGAdsgOG69iPUmf7i7OEZuJfnIXWf0S_qf23gsU5Ppr_lBnpP8pd1RRSQNwvFk_HiumdrJTm91cKenhvWEfbg8a9qhQCH4cwDCzbZ1mwR682WqApk0NOUK7w8UXR7kqIKrS9S2Y4azAvh-9zNWXB3lEkCtoZgDKgLBWotIc9cA8N5FVxd_WOYchA2BYBkgkisZtuW0CigJ4l5Om0zzJJypGGS22foyAdnHFbgkpcIW",
  "token_type": "bearer",
  "expires_in": 179
}

Invoking the following method I get "Hello World!".调用以下方法我得到“Hello World!”。

/*Method inside Homecontroller.cs that extends a controller*/
[Route("/api/HelloWorld")]
[HttpGet]
[Authorize] // How does the authorization works? 
public string HelloWorld()
{
    return "Hello World";
}

So very good but I want to know How all it works.非常好,但我想知道它是如何工作的。 If anyone has suggestions, texts, valid books/guides sources or something else I'll be grateful!如果有人有建议、文本、有效的书籍/指南来源或其他东西,我将不胜感激!

Thanks in advance提前致谢

"Also I don't know Who validates the token once I launch a Get/Post with the token. " “此外,一旦我使用令牌启动获取/发布,我也不知道谁会验证令牌。”

I believe somewhere in the request processing pipeline , checking is done to determine if the token is valid or not.我相信在请求处理管道中的某个地方,会进行检查以确定令牌是否有效。 if you take a look at the source code for AuthorizeAttribute如果您查看 AuthorizeAttribute 的源代码

protected virtual bool IsAuthorized(HttpActionContext actionContext)
        {
            if (actionContext == null)
            {
                throw Error.ArgumentNull("actionContext");
            }

            IPrincipal user = actionContext.ControllerContext.RequestContext.Principal;
            if (user == null || user.Identity == null || !user.Identity.IsAuthenticated)
            {
                return false;
            }

            if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
            {
                return false;
            }

            if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
            {
                return false;
            }

            return true;
        }

The IsAuthenticated property for user identity is already set.用户身份的 IsAuthenticated 属性已设置。 So if your token is valid IsAuthenticated would be true.因此,如果您的令牌有效,则 IsAuthenticated 为真。

The source code to AuthorizeAttribute can be found at here https://github.com/aspnet/AspNetWebStack/blob/main/src/System.Web.Http/AuthorizeAttribute.cs AuthorizeAttribute 的源代码可以在这里找到https://github.com/aspnet/AspNetWebStack/blob/main/src/System.Web.Http/AuthorizeAttribute.cs

According to this answer Where does Web API store generated tokens in order to validate subsequent requests?根据这个答案,Web API 在哪里存储生成的令牌以验证后续请求?

it is the OAuthBearerAuthenticationMiddleware that consumes your token during the early stage of request pipeline它是 OAuthBearerAuthenticationMiddleware 在请求管道的早期阶段消耗您的令牌

After doing some source code diving i found some information on OAuthBearerAuthenticationOptions and one of its property AccessTokenFormat在做了一些源代码潜水之后,我发现了一些关于 OAuthBearerAuthenticationOptions 及其属性 AccessTokenFormat 的信息

/// <summary>
        /// The data format used to un-protect the information contained in the access token.
        /// If not provided by the application the default data protection provider depends on the host server. 
        /// The SystemWeb host on IIS will use ASP.NET machine key data protection, and HttpListener and other self-hosted
        /// servers will use DPAPI data protection. If a different access token
        /// provider or format is assigned, a compatible instance must be assigned to the OAuthAuthorizationServerOptions.AccessTokenProvider 
        /// and OAuthAuthorizationServerOptions.AccessTokenFormat of the authorization server.
        /// </summary>
        public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; set; }

So when you are configuring your OAuthBearerAuthenticationOptions, if you didn't specify a AccessTokenFormat, then the default one will be used.因此,当您配置 OAuthBearerAuthenticationOptions 时,如果您没有指定 AccessTokenFormat,则将使用默认的。 And that depends on what host you are using.这取决于您使用的主机。

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

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