【发布时间】:2017-09-05 22:56:25
【问题描述】:
刚开始我的第一个 .net core 2 Web 应用程序实现。不幸的是,由于业务需求,用户必须通过遗留表单登录进行身份验证,用户名/密码被处理到 oracle db,当用户通过身份验证时,会生成一个会话 ID 并将其附加到启动的应用程序的基本 URL 中。非常古老的学校,但它有效。
您可以想象会话 ID 已过期,因此它必须由我的应用程序验证。很简单,我将从查询字符串中检索到的会话 ID 传递给我的 Oracle API,响应是一个包含用户信息(例如名字、姓氏等)的对象。
此 API 调用成功完成后,我创建一个新的 ClaimsIdentity 和 Principal 并调用 SignInAsync() 方法。
我目前在我的 Startup.cs 中注册的自定义中间件中执行此操作。我会在 Login 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);
}
【问题讨论】:
标签: c# asp.net .net asp.net-core claims-based-identity