Asp.Net 核心 - Identity SignInManager - 如何使用附加条件登录以便用户登录(例如:ClientId、用户名和密码))
Asp.Net Core - Identity SignInManager - How to signIn with an additional conditions in order for users to login (ex: ClientId, UserName and Password))
如何使用额外条件登录,在Asp.Net Core - Identity SignInManager
示例我想检查并验证 ClientId、用户名和登录密码。
类似这样的事情
var result = await SignInManager.PasswordSignInAsync(model.ClientId, model.Email, model.Password, model.RememberMe, shouldLockout: false);
请查看下面的完整代码
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}```
我建议使用 adapter pattern 方法,编写一个接口和包装器 class,在原始 SignInManager.PasswordSignInAsync 上实现该接口。
这个包装器 class 将有一个方法接收客户端 ID 和其余参数,执行验证,然后在完成后调用 SignInManager.PasswordSignInAsync。
您的登录方法将通过使用 .netCore dependency injection 到 startup.cs 的接口调用包装器 class。
public interface ISignInManagerAdapter
{
Task<Microsoft.AspNetCore.Identity.SignInResult> PasswordWithClientIdSignInAsync(string clientId, string userName, string password, bool isPersistent, bool lockoutOnFailure);
}
public class SignInManagerAdapter
{
private readonly IClientValidatorService _clientValidatorService;
public SignInManagerAdapter(IClientValidatorService clientValidatorService)
{
//you can add dependency injection interfaces to constructor parameter like below example.
this._clientValidatorService = clientValidatorService;
}
public async Task<Microsoft.AspNetCore.Identity.SignInResult> PasswordWithClientIdSignInAsync(string clientId, string userName, string password, bool isPersistent, bool lockoutOnFailure)
{
var validationStatus = _clientValidatorService.ValidateClientId(clientId);
if (validationStatus == "Active")
{
var result = await SignInManager.PasswordSignInAsync(model.ClientId, model.Email, model.Password, model.RememberMe, shouldLockout: false);
//do something
}
else
{
//do something
}
}
}
他们找到了不止一种解决方案,我选择扩展 signInManager。
@Markuzy的上述回答也是正确的,
这是我的代码
public class MySignInManager<TUser> : SignInManager<MyUser> where TUser : class
{
private readonly UserManager<MyUser> _userManager;
private readonly MyContext _dbContext;
private readonly IHttpContextAccessor _contextAccessor;
public MySignInManager(UserManager<MyUser> userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory<MyUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor, ILogger<SignInManager<MyUser>> logger, MyContext dbContext, IAuthenticationSchemeProvider schemeProvider, IUserConfirmation<MyUser> confirmation) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemeProvider, confirmation)
{
_userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
_contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
}
public override async Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure)
{
SignInResult signInResult = new SignInResult();
//Login not allowed - ClientId required to login
return await Task.FromResult(signInResult);
}
public async Task<SignInResult> PasswordSignInAsync(string clientId, string userName, string password, bool isPersistent, bool lockoutOnFailure)
{
if(CheckIsClientIdValid(username, password))
{
var result = await base.PasswordSignInAsync(userName, password, isPersistent, lockoutOnFailure);
return result;
}
else
{
SignInResult result = await Task.FromResult(new SignInResult());
//Login not allowed - ClientId mismatch
return result;
}
}
}
并根据
的顺序在Startup.cs中添加如下代码
services.AddSignInManager<MySignInManager<MyUser>>();
并用作
var result = await _signInManager.PasswordSignInAsync(Input.ClientId, Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
如何使用额外条件登录,在Asp.Net Core - Identity SignInManager
示例我想检查并验证 ClientId、用户名和登录密码。
类似这样的事情
var result = await SignInManager.PasswordSignInAsync(model.ClientId, model.Email, model.Password, model.RememberMe, shouldLockout: false);
请查看下面的完整代码
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}```
我建议使用 adapter pattern 方法,编写一个接口和包装器 class,在原始 SignInManager.PasswordSignInAsync 上实现该接口。
这个包装器 class 将有一个方法接收客户端 ID 和其余参数,执行验证,然后在完成后调用 SignInManager.PasswordSignInAsync。
您的登录方法将通过使用 .netCore dependency injection 到 startup.cs 的接口调用包装器 class。
public interface ISignInManagerAdapter
{
Task<Microsoft.AspNetCore.Identity.SignInResult> PasswordWithClientIdSignInAsync(string clientId, string userName, string password, bool isPersistent, bool lockoutOnFailure);
}
public class SignInManagerAdapter
{
private readonly IClientValidatorService _clientValidatorService;
public SignInManagerAdapter(IClientValidatorService clientValidatorService)
{
//you can add dependency injection interfaces to constructor parameter like below example.
this._clientValidatorService = clientValidatorService;
}
public async Task<Microsoft.AspNetCore.Identity.SignInResult> PasswordWithClientIdSignInAsync(string clientId, string userName, string password, bool isPersistent, bool lockoutOnFailure)
{
var validationStatus = _clientValidatorService.ValidateClientId(clientId);
if (validationStatus == "Active")
{
var result = await SignInManager.PasswordSignInAsync(model.ClientId, model.Email, model.Password, model.RememberMe, shouldLockout: false);
//do something
}
else
{
//do something
}
}
}
他们找到了不止一种解决方案,我选择扩展 signInManager。
@Markuzy的上述回答也是正确的,
这是我的代码
public class MySignInManager<TUser> : SignInManager<MyUser> where TUser : class
{
private readonly UserManager<MyUser> _userManager;
private readonly MyContext _dbContext;
private readonly IHttpContextAccessor _contextAccessor;
public MySignInManager(UserManager<MyUser> userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory<MyUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor, ILogger<SignInManager<MyUser>> logger, MyContext dbContext, IAuthenticationSchemeProvider schemeProvider, IUserConfirmation<MyUser> confirmation) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemeProvider, confirmation)
{
_userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
_contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
}
public override async Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure)
{
SignInResult signInResult = new SignInResult();
//Login not allowed - ClientId required to login
return await Task.FromResult(signInResult);
}
public async Task<SignInResult> PasswordSignInAsync(string clientId, string userName, string password, bool isPersistent, bool lockoutOnFailure)
{
if(CheckIsClientIdValid(username, password))
{
var result = await base.PasswordSignInAsync(userName, password, isPersistent, lockoutOnFailure);
return result;
}
else
{
SignInResult result = await Task.FromResult(new SignInResult());
//Login not allowed - ClientId mismatch
return result;
}
}
}
并根据
的顺序在Startup.cs中添加如下代码services.AddSignInManager<MySignInManager<MyUser>>();
并用作
var result = await _signInManager.PasswordSignInAsync(Input.ClientId, Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);