【发布时间】:2018-10-19 22:37:49
【问题描述】:
我正在我的控制器中调用一个方法并在其构造函数中命中一个断点。检查 User.Claims.First(...) 会引发异常,经过仔细调查,发现 User 是 null。
这是有道理的,因为控制器无法知道是谁调用它的匿名用户。然后我添加标题 Authorization 以 Bearer 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