了解 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