我正在将项目从.NET 4.6升级到.NET Core。它是具有使用EntityFramework的WebAPI的ASP.NET MVC网站。当(MVC或WebAPI)控制器启动DbContext时,有一些代码需要将用户标识为ClaimsIdentity来检查其声明。在以前的.NET中,像这样在Thread.CurrentPrincipal上最可靠地可用:
ClaimsIdentity identity = System.Threading.Thread.CurrentPrincipal.Identity as ClaimsIdentity;
IIRC,这是最安全的方法,因为您可能来自不同的上下文-WebAPI或ASP.NET MVC。
在.NET核心解决方案中,我尝试将Dependency注入IHttpContextAccessor到构造函数中,但是HttpContext上的User未获得授权并且没有声明
ClaimsIdentity identity = httpContext.HttpContext.User.Identity;
// identity.IsAuthenticated == false. identity.Claims is empty.
在Startup.cs中连接了安全性:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).
AddCookie(options =>
{
options.LoginPath = "/Login";
options.Cookie.HttpOnly = true;
}).
AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
var key = Configuration["Tokens:Key"];
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = Configuration["Tokens:Issuer"],
ValidAudience = Configuration["Tokens:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
};
});
用户在/ Login MVC视图页面上登录,该页面通过Cookies登录,并在另一个保存在客户端的请求中生成Bearer令牌。完成所有这些操作后,用户将被重定向到主页。
Cookie登录:
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = bIsPersistent });
令牌生成(从ajax调用,在重定向之前已保存到本地存储)
var secretKey = Configuration["Tokens:Key"];
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
var creds = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256 );
var expires = DateTime.Now.AddHours(8);
var token = new JwtSecurityToken(
_config["Tokens:Issuer"],
_config["Tokens:Issuer"],
oAuthIdentity.Claims,
expires: expires,
signingCredentials: creds
);
ret = Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
登陆到主页后,使用承载令牌对WebApi进行ajax调用(我将承载令牌从http请求中拉出并验证了jwt.io上的签名),并且webapi导致DbContext为实例化,这就是身份无效的地方。
好像身份没有正确地编组到DbContext-
如何在DbContext中获得正确的用户或身份?
此外,在这一点上我需要它在DbContext构造中,我对依赖注入没有很多控制权。但是我基本上需要从默认构造函数中获取此信息,或者以某种方式延迟加载它。
答案 0 :(得分:0)
使用您的设置,您有两个身份验证设置。因此,在Startup类的ConfigureServices
函数中,您需要使用如下代码:
services.AddAuthentication().AddCookie().AddJwtBearer();
请不要忘记指定默认身份验证。例如,如果您希望身份验证默认为cookie,则可以使用以下方法:
services.AddAuthentication("Cookies").AddCookie().AddJwtBearer();
或者为了保持代码的安全性,
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie().AddJwtBearer();
在启动类的Configure
函数中,不要忘记添加
app.UseAuthentication();
在控制器内进行身份验证时,如果不使用默认方案,则需要与[Authorize]
一起使用方案名称。
[Authorize(AuthenticationSchemes = "")]