在 Asp.Net Core 中使用旧用户 table 的自定义身份验证
Custom Authentication using legacy user table in Asp.Net Core
我需要从现有的遗留用户 Table 对用户进行身份验证,但如果可能的话,我想在身份和授权的肩上做这件事,以便我可以使用这些功能和属性。我们的大多数用户已经从一个更旧的本机应用程序登录,我们希望将其转移到我们的 Asp.net 核心 Intranet Web 应用程序。我在 SO 和其他地方看到了一些关于这个问题的主题,但 none 似乎适合我的特定需求。
解决此问题的最佳方法是什么?
Most of our users already have logins from a much older native
application that we want to carry over to our Asp.net Core Intranet
Web App.
您可以使用 OWIN cookie 身份验证中间件。中间件在 ASP.NET Core.
中稍作改动
仅供参考:Microsoft 正在转向基于策略的授权而不是基于角色。角色声明是为了向后兼容。如果您打算将 AuthorizeAttribute 与角色一起使用,您可能需要查看此 sample and usage.
https://leastprivilege.com/2016/08/21/why-does-my-authorize-attribute-not-work/
在登录操作方法中,我们首先使用现有的身份验证机制进行身份验证。然后将用户信息和角色名称传递给 SignManager 方法。
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
bool result = // Validate user
if (result)
{
var user = await _userRepository.GetUserByUserNameAsync(model.UserName);
var roleNames = (await _roleRepository.GetRolesForUser(user.Id))
.Select(r => r.Name).ToList();
await _signInManager.SignInAsync(user, roleNames);
}
else
{
ModelState.AddModelError("", "Incorrect username or password.");
}
}
return View("Login", model);
}
然后我们创建用户信息作为声明。
public class SignInManager
{
private readonly IHttpContextAccessor _httpContextAccessor;
public SignInManager(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public async Task SignInAsync(User user, IList<string> roleNames)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Sid, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.GivenName, user.FirstName),
new Claim(ClaimTypes.Surname, user.LastName)
};
foreach (string roleName in roleNames)
{
claims.Add(new Claim(ClaimTypes.Role, roleName));
}
var identity = new ClaimsIdentity(claims, "local", "name", "role");
var principal = new ClaimsPrincipal(identity);
await _httpContextAccessor.HttpContext.Authentication
.SignInAsync(Constants.AuthenticationScheme, principal);
}
public async Task SignOutAsync()
{
await _httpContextAccessor.HttpContext.Authentication
.SignOutAsync(Constants.AuthenticationScheme);
}
}
最后但同样重要的是,我们在 Startup.cs.
中添加 cookie 身份验证中间件
public void Configure(IApplicationBuilder app,
IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
Events = new CookieAuthenticationEvents
{
OnRedirectToAccessDenied = context =>
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return TaskCache.CompletedTask;
}
},
AuthenticationScheme = Constants.AuthenticationScheme,
LoginPath = new PathString("/Account/Login"),
AccessDeniedPath = new PathString("/Common/AccessDenied"),
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
...
}
我需要从现有的遗留用户 Table 对用户进行身份验证,但如果可能的话,我想在身份和授权的肩上做这件事,以便我可以使用这些功能和属性。我们的大多数用户已经从一个更旧的本机应用程序登录,我们希望将其转移到我们的 Asp.net 核心 Intranet Web 应用程序。我在 SO 和其他地方看到了一些关于这个问题的主题,但 none 似乎适合我的特定需求。
解决此问题的最佳方法是什么?
Most of our users already have logins from a much older native application that we want to carry over to our Asp.net Core Intranet Web App.
您可以使用 OWIN cookie 身份验证中间件。中间件在 ASP.NET Core.
中稍作改动仅供参考:Microsoft 正在转向基于策略的授权而不是基于角色。角色声明是为了向后兼容。如果您打算将 AuthorizeAttribute 与角色一起使用,您可能需要查看此 sample and usage.
https://leastprivilege.com/2016/08/21/why-does-my-authorize-attribute-not-work/
在登录操作方法中,我们首先使用现有的身份验证机制进行身份验证。然后将用户信息和角色名称传递给 SignManager 方法。
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
bool result = // Validate user
if (result)
{
var user = await _userRepository.GetUserByUserNameAsync(model.UserName);
var roleNames = (await _roleRepository.GetRolesForUser(user.Id))
.Select(r => r.Name).ToList();
await _signInManager.SignInAsync(user, roleNames);
}
else
{
ModelState.AddModelError("", "Incorrect username or password.");
}
}
return View("Login", model);
}
然后我们创建用户信息作为声明。
public class SignInManager
{
private readonly IHttpContextAccessor _httpContextAccessor;
public SignInManager(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public async Task SignInAsync(User user, IList<string> roleNames)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Sid, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.GivenName, user.FirstName),
new Claim(ClaimTypes.Surname, user.LastName)
};
foreach (string roleName in roleNames)
{
claims.Add(new Claim(ClaimTypes.Role, roleName));
}
var identity = new ClaimsIdentity(claims, "local", "name", "role");
var principal = new ClaimsPrincipal(identity);
await _httpContextAccessor.HttpContext.Authentication
.SignInAsync(Constants.AuthenticationScheme, principal);
}
public async Task SignOutAsync()
{
await _httpContextAccessor.HttpContext.Authentication
.SignOutAsync(Constants.AuthenticationScheme);
}
}
最后但同样重要的是,我们在 Startup.cs.
中添加 cookie 身份验证中间件public void Configure(IApplicationBuilder app,
IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
Events = new CookieAuthenticationEvents
{
OnRedirectToAccessDenied = context =>
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return TaskCache.CompletedTask;
}
},
AuthenticationScheme = Constants.AuthenticationScheme,
LoginPath = new PathString("/Account/Login"),
AccessDeniedPath = new PathString("/Common/AccessDenied"),
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
...
}