gpt4 book ai didi

c# - .NET Core 2 中间件解决方案中的 ClaimsIdentity 问题

转载 作者:行者123 更新时间:2023-11-30 16:42:46 29 4
gpt4 key购买 nike

刚刚开始我的第一个 .net core 2 网络应用程序实现。不幸的是,由于业务需求,用户必须通过遗留表单登录进行身份验证,用户名/密码被处理到 oracle 数据库,当用户通过身份验证时,将生成一个 session ID 并将其附加到启动的应用程序的基本 url。很老派,但很管用。

正如您想象的那样, session ID 已过期,因此它必须由我的应用程序进行验证。很简单,我将从查询字符串中检索到的 session ID 传递给我的 Oracle API,响应是一个包含用户信息(例如名字、姓氏等)的对象。

此 API 调用成功完成后,我将创建一个新的 ClaimsIdentity 和 Principal 并调用 SignInAsync() 方法。

我目前在我的 Startup.cs 中注册的自定义中间件中执行此操作。我会在登录 Controller 方法中以通常的方式处理此问题,但由于我的应用程序中没有登录,所以除了在我编写的中间件中,我看不到任何其他方式。

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 为假。

我在这里错过了什么?感谢您的建议,这是我以前不必处理的那些奇怪的边缘案例之一……因此需要自定义中间件。

    [HttpGet("claims")]
public async Task<IEnumerable<Claim>> Get()
{
var claims = (User as ClaimsPrincipal).Claims;
return await Task.FromResult(claims);
}

最佳答案

你真的不应该为此使用你自己的中间件。内置的身份验证和授权堆栈功能强大,足以应对您的情况。事实上,负责 ASP.NET Core 项目的身份验证堆栈的 .NET 安全 PM Barry Dorrans basically† said in a talk如果它不适用于您的用例,您应该给他发一封电子邮件,他们会修复它。

相反,您应该考虑为此目的编写自己的身份验证处理程序。这样,您就可以毫无障碍地获得整个身份验证和授权基础架构。一切都会正常进行。

为此,您基本上必须实现并注册一个 IAuthenticationHandler .

我建议您查看 CookieAuthenticationHandler因为它做了一种与您尝试做的类似的工作:根据随 HTTP 请求发送的信息重建声明身份。只是您使用的是查询参数和数据库而不是 cookie 数据。

根据您希望一般应用程序流程如何工作,您甚至可以考虑将其转变为远程身份验证提供程序,将其与 cookie 身份验证相结合——就像一个简化的 OAuth 流程:您收到一个请求,如果您这样做没有 cookie,您挑战重定向到您的旧登录掩码的自定义身份验证处理程序。在那里,您登录,它会将您发送回附加了 session ID 的应用程序的特殊 URL(例如 /signin-session?sessionid=12345)。您的远程身份验证处理程序处理该请求、查询数据库并根据信息构建身份并将其传递给 cookie 身份验证处理程序。然后,该身份会将身份保存在一个安全的 cookie 中,因此您不再需要在每次请求时查询数据库,也不再需要每个 URL 中的 session ID。

†​​ 公平地说,他只是在谈论那里的授权部分;但我敢肯定他对整个堆栈也是这么想的,因为它真的很强大。

关于c# - .NET Core 2 中间件解决方案中的 ClaimsIdentity 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46064417/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com