C# 调用控制器时,何时分配用户的身份?
我正在调用控制器中的一个方法,并在其构造函数中命中一个断点。检查User.Claims.First(…)会抛出一个异常,经过仔细调查后,发现该用户为null 这是有道理的,因为控制器不知道调用它的匿名用户是谁。然后,我添加了头授权,通过持有者xxx.yyy.zzz(邮递员和我的应用程序)对其进行估价。令牌是正确的,因为篡改它会导致状态代码401未经授权 因此,我的结论是,安全设置起作用了,策略的行为与预期的一样(使用与缺少所述操作的权限的用户对应的令牌进行调用,但不会执行所述操作) 将令牌文本粘贴到jwt.io可以提供有关声明的预期详细信息。因此,我的结论是令牌应该是可读的,并且可以被应用程序的库解析 所以问题是这个用户如何为控制器实例化(何时、何地、基于什么?或者,如何搜索它(我已经尝试了一段时间,但我意识到我正在黑暗中摸索一棵随机树) 令牌以以下方式配备索赔C# 调用控制器时,何时分配用户的身份?,c#,asp.net-core,jwt,claims-based-identity,C#,Asp.net Core,Jwt,Claims Based Identity,我正在调用控制器中的一个方法,并在其构造函数中命中一个断点。检查User.Claims.First(…)会抛出一个异常,经过仔细调查后,发现该用户为null 这是有道理的,因为控制器不知道调用它的匿名用户是谁。然后,我添加了头授权,通过持有者xxx.yyy.zzz(邮递员和我的应用程序)对其进行估价。令牌是正确的,因为篡改它会导致状态代码401未经授权 因此,我的结论是,安全设置起作用了,策略的行为与预期的一样(使用与缺少所述操作的权限的用户对应的令牌进行调用,但不会执行所述操作) 将令牌文本粘
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);
编辑启动设置如下
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(...);
}
我通过分析事件管道(如@amy所述)解决了这个问题,并注意到操作调用之前有OnActionExecuting方法(由@sixtosaez提供)
我可以想象,在Start中更改中间件的注册顺序(如@MarkG所述)也可以开始工作,但由于不存在任何问题和混乱,我对处理这些问题没有信心。用户原则是在身份验证中间件中设置的。对于cookie中间件,这发生在
CookieAuthenticationHandler.AuthenticateCoreAsync
中。如果您共享启动代码,这将非常有用。中间件的顺序也很重要。@MarkG很抱歉忽略了这一点。很明显,你提到了。然而,直到现在我才意识到这一点。请稍后查看编辑。@Amy我已经用启动更新了问题。我可以看到在哪里进行身份验证和授权。然而,我不清楚哪些步骤对应于控制器构造函数的调用。请告知。(另外,我使用的不是cookies,而是JWTokens,如果这有什么意义的话。)@DonkeyBanana您所问的是Web API管道:更改中间件的注册顺序是什么意思?玩弄这些东西没什么害处……这是学习的最佳方式。@Brad如果你查看对问题的评论,你会看到MarkG说中间件注册的顺序确实会影响执行顺序的行为。因为我在总结别人说的话,所以我也想把这条信息带进来。然而,由于我还没有尝试过,我不能保证它确实解决了我的问题。@Brad我决不是在暗示,如果一个人想要学习,就玩弄注册顺序是有害的。不过,我没有时间,其他提示实际上解决了我的问题。我选择了不篡改中间件,因为我担心会对应用程序中的其他内容造成损害。如果您觉得可以就中间件的基于订单的原始问题解决方案提供建议,那么欢迎并敦促您发布建议。实际上,您还没有显示中间件注册的顺序。中间件通常使用app.UseXXX(…)在Startup.Configure(IAApplicationBuilder app)
方法中注册代码>语句和顺序非常重要。您只显示了您的服务注册services.AddXXX(…)不影响请求管道和顺序的代码>并不总是重要的,这取决于您注册的服务(如果在构建IServiceProvider
之前未注册其他服务,则某些服务可能引发异常)。@Brad So Dumble。。。当然,你是对的。我被所有的东西弄糊涂了,最后忘了发了。请看一下最新的问题。
public override void OnActionExecuting(ActionExecutingContext context)
{
Claim claim = User.Claims
.First(_ => _.Type == "MemberId");
...
}