Sto aggiornando un progetto da .NET 4.6 a .NET Core. È un sito Web ASP.NET MVC con WebAPI che utilizza EntityFramework. Quando il controller a (MVC o WebAPI) attiva DbContext, esiste un codice che deve identificare l'utente come ClaimsIdentity per ispezionare le proprie attestazioni. In .NET precedente, questo era il più affidabile disponibile su Thread.CurrentPrincipal in questo modo:
ClaimsIdentity identity = System.Threading.Thread.CurrentPrincipal.Identity as ClaimsIdentity;
IIRC, questo era il modo più sicuro di farlo poiché potresti provenire da diversi contesti: WebAPI o ASP.NET MVC.
Nella soluzione core .NET, ho provato a Dependency Inject a IHttpContextAccessor nel costruttore, ma l'utente su HttpContext non è autorizzato e non ha rivendicazioni
ClaimsIdentity identity = httpContext.HttpContext.User.Identity;
// identity.IsAuthenticated == false. identity.Claims is empty.
La sicurezza è cablata in 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))
};
});
L'utente accede a una pagina di visualizzazione / Login MVC, che accede tramite Cookie e genera anche un token Bearer in un'altra richiesta che viene salvata sul client. Dopo tutto questo l'utente viene reindirizzato alla homepage.
Login cookie:
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = bIsPersistent });
Generazione di token (chiamata da ajax, salvata in localstorage prima del reindirizzamento)
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) });
Dopo l'atterraggio sulla home page, viene effettuata una chiamata ajax al WebApi con il token al portatore (ho rimosso il token al portatore dalla richiesta http e verificato la firma su jwt.io) e il webapi causa l'istanziazione di DbContext e questo è dove l'identità non è valida.
È come se l'identità non fosse correttamente indirizzata al DbContext -
Come ottenere l'utente o l'identità corretti in DbContext?
Inoltre, al punto che mi serve è nella costruzione di DbContext, che non ho molto controllo sull'Iniezione di dipendenza. Ma ho bisogno di ottenere queste informazioni fondamentalmente da un costruttore predefinito o pigro caricarlo in qualche modo.
Con la configurazione, hai due impostazioni di autenticazione. Quindi, nella funzione ConfigureServices
nella classe Startup, è necessario utilizzare qualcosa di simile al seguente:
services.AddAuthentication().AddCookie().AddJwtBearer();
Non dimenticare di specificare un'autenticazione predefinita. Ad esempio, se si desidera che l'autenticazione sia cookie per impostazione predefinita, è possibile utilizzare questo:
services.AddAuthentication("Cookies").AddCookie().AddJwtBearer();
O per mantenere il codice più sicuro,
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie().AddJwtBearer();
Nella tua classe di avvio, nella funzione Configure
, non dimenticare di aggiungere
app.UseAuthentication();
Quando si esegue l'autenticazione all'interno di un controller, sarà necessario utilizzare il nome dello schema insieme a [Authorize]
se non si utilizza lo schema predefinito.
[Authorize(AuthenticationSchemes = "")]