![](/img/trans.png)
[英]How to manipulate the ClaimsIdentity of current token using middleware in .net core app?
[英]Issue With ClaimsIdentity In .NET Core 2 Middleware Solution
剛開始我的第一個.net核心2 Web應用程序實現。 不幸的是,由於業務需求,用戶必須通過遺留表單登錄進行身份驗證,用戶名/密碼將被處理到oracle db,並且當用戶通過身份驗證時,會生成會話ID並將其附加到啟動的應用程序的基本URL。 很老的學校,但它的工作原理。
您可以想象會話ID到期,因此必須由我的應用程序驗證。 很簡單,我將從查詢字符串檢索的會話ID傳遞給我的Oracle API,響應是一個包含用戶信息的對象,如firstname,lastname等。
在此API調用成功完成后,我創建一個新的ClaimsIdentity和Principal並調用SignInAsync()方法。
我目前在我在Startup.cs中注冊的自定義中間件中執行此操作。 我會在登錄控制器方法中以常規方式處理這個問題,但由於我的應用程序中沒有登錄,我看不到任何其他方式,但在我編寫的中間件中。
public class AuthenticationHandler
{
private readonly RequestDelegate _next;
private HttpService _httpService;
public AuthenticationHandler(RequestDelegate next, HttpService httpService)
{
_httpService = httpService;
_next = next;
}
public async Task Invoke(HttpContext context, [FromServices] HttpService httpService)
{
if (context.Request.Query.Count == 1)
{
var sessionId = context.Request.Query.FirstOrDefault().Value;
var session = await _httpService.ValidateSession(sessionId);
if (!string.IsNullOrEmpty(session?.UserId))
{
var claims = new List<Claim>()
{
new Claim(CustomClaimTypes.UserId, session.UserId),
new Claim(CustomClaimTypes.BuId, session.BuId),
new Claim(CustomClaimTypes.SecurityLevel, session.SecurityLevel)
};
var identity = new ClaimsIdentity(claims, "TNReadyEVP");
var principal = new ClaimsPrincipal(identity);
await Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.SignInAsync(context, principal);
var isIn = principal.Identity.IsAuthenticated;
var isAuthed = (context.User.Identity as ClaimsIdentity).IsAuthenticated;
await _next.Invoke(context);
}
else
{
Terminate(context);
}
}
return;
}
private async void Terminate(HttpContext context)
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid User");
return;
}
}
public static class MiddlewareExtensions
{
public static IApplicationBuilder ValidateSession(this IApplicationBuilder builder)
{
return builder.UseMiddleware<AuthenticationHandler>();
}
}
到目前為止這么好,我相信這是正確的解決方案。 但是,當我嘗試通過我的應用程序中的小API獲取聲明時,如下所示,聲明為空,User.Identity.Authenticated為false。
我在這里錯過了什么? 感謝您的建議,這是我之前沒有處理過的那些奇怪的邊緣情況之一......因此需要定制中間件。
[HttpGet("claims")]
public async Task<IEnumerable<Claim>> Get()
{
var claims = (User as ClaimsPrincipal).Claims;
return await Task.FromResult(claims);
}
你真的不應該使用自己的中間件。 內置的身份驗證和授權堆棧功能強大,足以處理您的情況。 事實上,負責ASP.NET核心項目的auth堆棧的.NET安全PM Barry Dorrans 基本上†在一次談話中說 ,如果它不適合你的用例,你應該給他發一封電子郵件,他們會修理它。
相反,您應該考慮為此目的編寫自己的身份驗證處理程序。 這樣,您就可以獲得整個身份驗證和授權基礎架構,而無需額外的障礙。 一切都會奏效。
為此,您基本上必須實現並注冊IAuthenticationHandler
。
我建議您查看CookieAuthenticationHandler
因為它與您嘗試執行的操作類似:從HTTP請求發送的信息中重建聲明標識。 只是您正在使用查詢參數和數據庫而不是cookie數據。
根據您希望一般應用程序流的工作方式,您甚至可以考慮將其轉換為遠程身份驗證提供程序,將其與cookie身份驗證相結合 - 就像一個愚蠢的OAuth流程:您收到請求,如果您沒有cookie,您挑戰自定義身份驗證處理程序,該處理程序重定向到您的舊登錄掩碼。 在那里,您登錄並將其發送回您的應用程序的特殊URL,其中附加了會話ID(例如/signin-session?sessionid=12345
)。 您的遠程身份驗證處理程序處理該請求,查詢數據庫並根據信息構造標識並將其傳遞給cookie身份驗證處理程序。 然后,那個人將身份保存在安全cookie中,因此您不再需要在每個請求上查詢數據庫,並且您也不再需要每個URL中的會話ID。
†公平地說,他只談到那里的授權部分; 但我確信他也意味着整個堆棧,因為它真的很強大。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.