using SignInResult = Microsoft.AspNetCore.Identity.SignInResult;
namespace Dpz.Core.Web.Library;
public class UserStore : IUserStore<VmUserInfo>
{
private readonly IAccountService _accountService;
public UserStore(IAccountService accountService)
{
_accountService = accountService;
}
public void Dispose()
{
}
public async Task<string> GetUserIdAsync(VmUserInfo user, CancellationToken cancellationToken)
{
return await Task.Run(() => user.Id, cancellationToken);
}
public async Task<string?> GetUserNameAsync(VmUserInfo user, CancellationToken cancellationToken)
{
return await Task.Run(() => user.Name, cancellationToken);
}
public async Task SetUserNameAsync(VmUserInfo user, string? userName, CancellationToken cancellationToken)
{
await Task.Run(() => user.Name = userName, cancellationToken);
}
public async Task<string?> GetNormalizedUserNameAsync(VmUserInfo user, CancellationToken cancellationToken)
{
return await Task.Run(() => user.Name, cancellationToken);
}
public async Task SetNormalizedUserNameAsync(VmUserInfo user, string? normalizedName,
CancellationToken cancellationToken)
{
await Task.Run(() => user.Name = normalizedName, cancellationToken);
}
public Task<IdentityResult> CreateAsync(VmUserInfo user, CancellationToken cancellationToken)
{
throw new System.NotImplementedException();
}
public Task<IdentityResult> UpdateAsync(VmUserInfo user, CancellationToken cancellationToken)
{
throw new System.NotImplementedException();
}
public Task<IdentityResult> DeleteAsync(VmUserInfo user, CancellationToken cancellationToken)
{
throw new System.NotImplementedException();
}
public async Task<VmUserInfo?> FindByIdAsync(string userId, CancellationToken cancellationToken)
{
return await _accountService.GetOneUserAsync(userId);
}
public async Task<VmUserInfo?> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
return await _accountService.GetUserInfoByNameAsync(normalizedUserName);
}
}
public class UserInfoClaimsPrincipalFactory : IUserClaimsPrincipalFactory<VmUserInfo>
{
public async Task<ClaimsPrincipal> CreateAsync(VmUserInfo user)
{
return await Task.Run(() =>
{
var claims = user.GetType().GetProperties()
.Select(x => new Claim(x.Name, x.GetValue(user)?.ToString() ?? "")).ToList();
claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id));
var principal =
new ClaimsPrincipal(new ClaimsIdentity(claims, Program.AuthorizeCookieName, "Name", "Permissions"));
return principal;
});
}
}
public interface IApplicationSignInManager
{
Task SignInAsync(VmUserInfo user, AuthenticationProperties authenticationProperties,
string? authenticationMethod = null);
Task<SignInResult> CheckPasswordSignInAsync(VmUserInfo user, string password,
bool lockoutOnFailure);
Task<SignInResult> PasswordSignInAsync(string userName, string password,
bool isPersistent, bool lockoutOnFailure);
Task RefreshSignInAsync(VmUserInfo user);
bool IsSignedIn(ClaimsPrincipal principal);
Task SignInWithClaimsAsync(VmUserInfo user,
AuthenticationProperties authenticationProperties, IEnumerable<Claim> additionalClaims);
}
public class ApplicationSignInManager : SignInManager<VmUserInfo>, IApplicationSignInManager
{
private readonly IAccountService _accountService;
private readonly UserManager<VmUserInfo> _userManager;
private readonly IAuthenticationSchemeProvider _schemes;
private readonly IHybridCachingProvider _cachingProvider;
private readonly IHttpContextAccessor _contextAccessor;
private readonly IUserClaimsPrincipalFactory<VmUserInfo> _claimsFactory;
private readonly ILogger<ApplicationSignInManager> _logger;
public ApplicationSignInManager(
IAccountService accountService,
UserManager<VmUserInfo> userManager,
IHttpContextAccessor contextAccessor,
IUserClaimsPrincipalFactory<VmUserInfo> claimsFactory,
IOptions<IdentityOptions> optionsAccessor,
ILogger<ApplicationSignInManager> logger,
IAuthenticationSchemeProvider schemes,
IUserConfirmation<VmUserInfo> userConfirmation,
IHybridCachingProvider cachingProvider) :
base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, userConfirmation)
{
_accountService = accountService;
_userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
_logger = logger;
_schemes = schemes;
_cachingProvider = cachingProvider;
_contextAccessor = contextAccessor;
_claimsFactory = claimsFactory;
}
public override async Task SignInAsync(VmUserInfo user, AuthenticationProperties authenticationProperties,
string? authenticationMethod = null)
{
ClaimsPrincipal userPrincipalAsync = await base.CreateUserPrincipalAsync(user);
if (authenticationMethod != null)
userPrincipalAsync.Identities.First().AddClaim(new Claim(
"https://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod",
authenticationMethod));
await Context.SignInAsync(Program.AuthorizeCookieName, userPrincipalAsync,
authenticationProperties ?? new AuthenticationProperties());
}
public override async Task<SignInResult> CheckPasswordSignInAsync(VmUserInfo user, string password,
bool lockoutOnFailure)
{
var userInfo = await _accountService.LoginAsync(user.Id, (user.Id + password).GenerateMd5());
if (userInfo == null)
return SignInResult.Failed;
user = userInfo;
return SignInResult.Success;
//return base.CheckPasswordSignInAsync(user, password, lockoutOnFailure);
}
public override async Task<SignInResult> PasswordSignInAsync(string userName, string password,
bool isPersistent, bool lockoutOnFailure)
{
var userInfo = await _accountService.LoginAsync(userName, (userName + password).GenerateMd5());
if (userInfo == null)
return SignInResult.Failed;
var result = await base.SignInOrTwoFactorAsync(userInfo, isPersistent, null, false);
if (result.Succeeded)
{
await _cachingProvider.SetAsync(_userInfoKey(userName), userInfo, TimeSpan.FromDays(14));
}
return result;
}
private readonly Func<string, string> _userInfoKey = x => $"account-info-{x}";
public override async Task RefreshSignInAsync(VmUserInfo user)
{
_logger.LogInformation("refresh sign");
var authenticateResult = await Context.AuthenticateAsync(Program.AuthorizeCookieName);
await Context.SignInAsync(Program.AuthorizeCookieName, await _claimsFactory.CreateAsync(user),
authenticateResult?.Properties);
}
/// <summary>
/// 判断应用程序cookie身份
/// </summary>
/// <param name="principal"></param>
/// <returns></returns>
public override bool IsSignedIn(ClaimsPrincipal principal)
{
_logger.LogInformation("IsSignedIn");
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return principal.Identities.Any(i => i.AuthenticationType == Program.AuthorizeCookieName);
}
/// <summary>
/// 登录指定的用户 <see cref="VmUserInfo"/>
/// </summary>
/// <param name="user"></param>
/// <param name="authenticationProperties"></param>
/// <param name="additionalClaims"></param>
/// <returns></returns>
public override async Task SignInWithClaimsAsync(VmUserInfo user,
AuthenticationProperties? authenticationProperties, IEnumerable<Claim> additionalClaims)
{
_logger.LogInformation("SignInWithClaimsAsync");
var userPrincipal = await CreateUserPrincipalAsync(user);
foreach (var claim in additionalClaims)
{
userPrincipal.Identities.First().AddClaim(claim);
}
await Context.SignInAsync(Program.AuthorizeCookieName,
userPrincipal,
authenticationProperties ?? new AuthenticationProperties());
}
}