网站首页 网站源码
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 IFusionCache _fusionCache;
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,
IFusionCache fusionCache
)
: base(
userManager,
contextAccessor,
claimsFactory,
optionsAccessor,
logger,
schemes,
userConfirmation
)
{
_accountService = accountService;
_userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
_logger = logger;
_schemes = schemes;
_fusionCache = fusionCache;
_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 _fusionCache.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()
);
}
}
上述代码实现了一个用户身份验证和管理的系统,主要使用了 ASP.NET Core Identity 框架。以下是代码的主要组成部分及其功能的详细解释:
UserStore
类UserStore
类实现了 IUserStore<VmUserInfo>
接口,负责用户的存储和管理。它使用一个 IAccountService
服务来与用户数据进行交互。主要功能包括:
GetUserIdAsync
和 GetUserNameAsync
方法获取用户的 ID 和用户名。SetUserNameAsync
和 SetNormalizedUserNameAsync
方法设置用户的用户名。FindByIdAsync
和 FindByNameAsync
方法根据用户 ID 或用户名查找用户。NotImplementedException
),但它们的存在表明该类的设计是为了支持这些操作。UserInfoClaimsPrincipalFactory
类UserInfoClaimsPrincipalFactory
类实现了 IUserClaimsPrincipalFactory<VmUserInfo>
接口,负责创建用户的 ClaimsPrincipal
对象。ClaimsPrincipal
是一个表示用户的身份和声明的对象。主要功能包括:
CreateAsync
方法,使用用户的属性生成一组声明,并将其封装在 ClaimsPrincipal
中。IApplicationSignInManager
接口IApplicationSignInManager
接口定义了一组用于用户登录和身份验证的方法,包括:
SignInAsync
和 SignInWithClaimsAsync
方法用于登录用户。CheckPasswordSignInAsync
和 PasswordSignInAsync
方法用于验证用户的密码。RefreshSignInAsync
方法用于刷新用户的登录状态。IsSignedIn
方法用于检查用户的身份。ApplicationSignInManager
类ApplicationSignInManager
类继承自 SignInManager<VmUserInfo>
,实现了 IApplicationSignInManager
接口,提供了用户登录的具体实现。主要功能包括:
SignInAsync
和 PasswordSignInAsync
方法,使用 IAccountService
进行用户身份验证,并在成功后创建用户的 ClaimsPrincipal
。CheckPasswordSignInAsync
方法,使用 IAccountService
验证用户的密码。RefreshSignInAsync
方法,更新用户的登录信息。IsSignedIn
方法,检查用户是否已登录。SignInWithClaimsAsync
方法允许在登录时附加额外的声明。整体来看,这段代码实现了一个基于 ASP.NET Core Identity 的用户身份验证系统,提供了用户的存储、管理和身份验证功能。通过 UserStore
和 ApplicationSignInManager
类,系统能够处理用户的登录、密码验证、用户信息管理等操作。UserInfoClaimsPrincipalFactory
则负责将用户信息转换为可用于身份验证的声明。