【问题标题】:When is the identity of User assigned when invoking a controller?调用控制器时何时分配用户的身份?
【发布时间】:2018-10-19 22:37:49
【问题描述】:

我正在我的控制器中调用一个方法并在其构造函数中命中一个断点。检查 User.Claims.First(...) 会引发异常,经过仔细调查,发现 Usernull

这是有道理的,因为控制器无法知道是谁调用它的匿名用户。然后我添加标题 AuthorizationBearer xxx.yyy.zzz (邮递员以及我的 Angular 应用程序)对其进行评估。令牌是正确的,因为篡改它会导致状态代码401 Unauthorized

因此,我的结论是,安全设置有效,策略的行为符合预期(使用与没有执行上述操作权限的用户对应的令牌调用)。

将令牌文本粘贴到 jwt.io 可以提供有关声明的预期详细信息。因此,我的结论是,该令牌应该对应用程序的库是可读和可解析的。

所以问题是这样的。 User 是如何为控制器实例化的(何时、何地、基于什么)? 或者,如何用谷歌搜索它(我已经尝试了一段时间,但我意识到我我在黑暗中摸索着乱叫一棵树)。

令牌以下列方式配备声明。

Claim[] claims =
{
  new Claim(ClaimTypes.Expiration, TokenExpiration.ToString(), ClaimValueTypes.DateTime),
  new Claim(ClaimTypes.Name, userName, ClaimValueTypes.String),
  new Claim(ClaimTypes.Role, member.Privilege + "", ClaimValueTypes.Integer),
  new Claim(ClaimTypes.Version, "0.1", ClaimValueTypes.String),
  new Claim(ClaimTypes.Webpage, "xxx.azurewebsites.net", ClaimValueTypes.String),
  new Claim("NetworkId", member.Network.Id.ToString(), ClaimValueTypes.String),
  new Claim("MemberId", member.Id.ToString(), ClaimValueTypes.String),
  new Claim("Author", "yyy", ClaimValueTypes.String)
};
SymmetricSecurityKey key = new SymmetricSecurityKey(SecurityKey);
SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

JwtSecurityToken token = new JwtSecurityToken(
  "xxx.azurewebsites.net",
  "xxx.azurewebsites.net",
  claims,
  DateTime.UtcNow,
  TokenExpiration,
  credentials);
string output = new JwtSecurityTokenHandler().WriteToken(token);

editStartup设置如下。

services.AddSingleton<IUtilityService, UtilityService>();
services.AddSingleton<IEmailService, EmailService>();
services.AddCors(_ => _.AddPolicy("Open policy", __ => __
  .AllowAnyOrigin()
  .AllowAnyHeader()
  .AllowAnyMethod()));
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(_ =>
  {
    _.TokenValidationParameters = new TokenValidationParameters
    {
      ValidateIssuerSigningKey = true,
      ValidateAudience = false,
      ValidateIssuer = false,
      ValidateActor = true,
      ValidateLifetime = true,
      IssuerSigningKey = new SymmetricSecurityKey( ... )
    };
  });
  services.AddAuthorization(_ => _.AddPolicy("Common", __ => ... ));
  services.AddAuthorization(_ => _.AddPolicy("Super", __ => ... ));
  services.AddAuthorization(_ => _.AddPolicy("Admin", __ => ... ));
  services.AddMvc()
    .AddJsonOptions(_ => ...);
  services.AddSwaggerGen(_ => ... );
  services.AddDbContext<Context>(_ => _.UseSqlServer( ... ));

再次编辑配置设置如下。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  if (env.IsDevelopment())
    app.UseDeveloperExceptionPage();

  app.Use(async (context, next) =>
  {
    try { await next(); }
    catch (Exception) { context.Response.StatusCode = ... }
  });

  app.UseCors("Open policy");
  app.UseAuthentication();
  app.UseMvc();
  app.UseSwagger();
  app.UseSwaggerUI(...);
}

【问题讨论】:

  • 用户原则在认证中间件中设置。对于 cookie 中间件,这发生在 CookieAuthenticationHandler.AuthenticateCoreAsync
  • 如果你分享你的启动代码会很有用。中间件的顺序也很重要。
  • @MarkG 很抱歉省略了这一点。现在你提到它有点明显。然而,直到现在我才意识到这一点。请稍后查看编辑。
  • @Amy 我已经用我的 Startup 更新了这个问题。我可以看到身份验证和授权发生在哪里。但是,我不清楚哪个步骤对应于控制器构造函数的调用。请指教。 (另外,我使用的不是 cookie,而是 JWTokens,如果这有任何意义的话。)
  • @DonkeyBanana 您要问的是 Web API 管道:dotnetcurry.com/aspnet/888/aspnet-webapi-message-lifecycle

标签: c# asp.net-core jwt claims-based-identity


【解决方案1】:

我通过分析事件管道(如 @amy 所述)解决了这个问题,并注意到动作调用之前是 OnActionExecuting 方法(shown in the PDF@sixtosaez 提供)。

public override void OnActionExecuting(ActionExecutingContext context)
{
  Claim claim = User.Claims
    .First(_ => _.Type == "MemberId");
  ...
}

我想也可以通过在 Start 中更改中间件的注册顺序来开始工作(正如@MarkG 所提到的),但我没有信心解决这个问题变得幼稚和混乱。

【讨论】:

  • 更改中间件的注册顺序是什么意思?玩这些东西并没有什么坏处……这是最好的学习方式。
  • @Brad 如果您检查问题的 cmets,您会看到 MarkG 指出注册中间件的顺序确实会影响执行顺序的行为。由于我正在总结其他人所说的内容,因此我也想引入那条信息。但是,由于我没有尝试过,我不能保证它确实解决了我的问题。
  • @Brad 绝不是暗示如果要学习,玩弄注册顺序是有害的。不过,我没有时间,其他提示实际上解决了我的问题。我接受了它并选择不篡改中间件,因为我担心我会对我的应用程序中的其他东西造成损害。如果您认为您可以就中间件的基于订单的解决方案对原始问题提出建议,欢迎并敦促您发布它。
  • 你居然没有显示中间件注册的顺序。中间件通常使用app.UseXXX(...); 语句在Startup.Configure(IApplicationBuilder app) 方法中注册,并且顺序非常重要。您只显示了您的服务注册services.AddXXX(...);,这不会影响请求管道,并且顺序并不总是很重要,具体取决于您注册的服务(如果在构建 IServiceProvider 之前未注册其他服务,某些服务可能会引发异常) .
  • @Brad 好蠢……当然,你是对的。我被所有的东西弄糊涂了,最后忘记了。请看一下更新后的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 2019-03-20
  • 1970-01-01
  • 1970-01-01
  • 2021-05-02
  • 1970-01-01
相关资源
最近更新 更多