繁体   English   中英

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

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

我正在开发一个 MVC 项目,我正在生成一个令牌来授权任何拥有它的人说著名的“Hello World!”。 由于我是 ASP.NET 中的新手,因此我不了解 WHERE 和 WHO 生成令牌的位置,以及生成后将其保存在何处(或如何)。 此外,一旦我使用令牌启动获取/发布,我也不知道谁会验证令牌。 最终目的是尝试改变生成的令牌类型,获得一个像 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";
}

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

提前致谢

“此外,一旦我使用令牌启动获取/发布,我也不知道谁会验证令牌。”

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

根据这个答案,Web API 在哪里存储生成的令牌以验证后续请求?

它是 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,则将使用默认的。 这取决于您使用的主机。

暂无
暂无

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

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