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

Posted

技术标签:

【中文标题】了解 ASP.NET(MVC、Web API)中的令牌生成/验证【英文标题】:Understanding Token Generation/Validation in ASP.NET (MVC, web API) 【发布时间】:2021-02-01 14:00:12 【问题描述】:

我正在开发一个 MVC 项目,在该项目中我正在生成一个令牌以授权任何拥有它的人说出著名的“Hello World!”。 由于我是 ASP.NET 中的新人,因此我不了解 WHERE 和 WHO 生成令牌的位置,以及生成令牌后保存在何处(或如何保存)。此外,一旦我使用令牌启动 Get/Post,我也不知道谁验证了令牌。 最终目的是尝试更改生成的令牌类型,获得一个新的类似 JWT 令牌,而不是基本令牌。 我正在使用 OWIN。

以下是我认为重要的部分。

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());
    

然后我按照一些指南开发了一个提供程序,结果是这样的:

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??*/
    

使用 Postman 我得到这样的结果。


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

调用以下方法我得到“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";

非常好,但我想知道它是如何工作的。 如果有人有建议、文本、有效的书籍/指南来源或其他东西,我将不胜感激!

提前致谢

【问题讨论】:

See if this helps 基本思想是您的中间件将验证令牌。您将在用户登录时生成,并且不需要存储它。如果你为 jwt asp.net core 做简单的 google,那么有很多关于它是如何工作的细节。 【参考方案1】:

“我也不知道一旦我使用令牌启动 Get/Post 后谁验证了令牌。”

我相信在请求处理管道的某个地方,会进行检查以确定令牌是否有效。如果你看一下 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;
        

已设置用户身份的 IsAuthenticated 属性。因此,如果您的令牌有效,IsAuthenticated 将是正确的。

AuthorizeAttribute 的源代码可以在这里找到 https://github.com/aspnet/AspNetWebStack/blob/main/src/System.Web.Http/AuthorizeAttribute.cs

根据这个回答Where does Web API store generated tokens in order to validate subsequent requests?

它是 OAuthBearerAuthenticationMiddleware 在请求管道的早期阶段使用您的令牌

在做了一些源代码潜水后,我发现了一些关于 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; 

因此,当您配置 OAuthBearerAuthenticationOptions 时,如果您没有指定 AccessTokenFormat,那么将使用默认的。这取决于您使用的主机。

【讨论】:

以上是关于了解 ASP.NET(MVC、Web API)中的令牌生成/验证的主要内容,如果未能解决你的问题,请参考以下文章

正确处理 ASP.net MVC 4 Web Api 路由中的嵌套资源

从 ASP.NET MVC Web API 中的多个表单数据键接收文件

ASP.NET MVC Web.Api 路由 - 真实世界示例

使用 ASP.NET Core MVC 创建 Web API

Web API系列教程2.1 — ASP.NET Web API中的路由机制

ASP.NET Web API将MV响应转换为MVC 4中的json List