a、Core Layer - Authorizasion.Users.UserStore.cs
public class UserStore : AbpUserStore<Role, User>
{
private readonly IRepository<User, long> _userRepository;
public UserStore(
IUnitOfWorkManager unitOfWorkManager,
IRepository<User, long> userRepository,
IRepository<Role> roleRepository,
IAsyncQueryableExecuter asyncQueryableExecuter,
IRepository<UserRole, long> userRoleRepository,
IRepository<UserLogin, long> userLoginRepository,
IRepository<UserClaim, long> userClaimRepository,
IRepository<UserPermissionSetting, long> userPermissionSettingRepository,
IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository,
IRepository<OrganizationUnitRole, long> organizationUnitRoleRepository)
: base(
unitOfWorkManager,
userRepository,
roleRepository,
asyncQueryableExecuter,
userRoleRepository,
userLoginRepository,
userClaimRepository,
userPermissionSettingRepository,
userOrganizationUnitRepository,
organizationUnitRoleRepository)
{
_userRepository = userRepository;
}
/// <summary>
/// Retrieves a user by their account identifier
/// </summary>
/// <param name="account">The account identifier</param>
/// <returns>The matching user or null</returns>
public virtual async Task<User> FindByAccountAsync(string account)
{
account = account.ToLower();
return await _userRepository.FirstOrDefaultAsync(
user => user.UserName.ToLower() == account
);
}
}
b、Core Layer - Authorization.LogInManager.cs
public class LogInManager : AbpLogInManager<Tenant, Role, User>
{
private readonly UserStore _userStore;
private readonly AbpUserManager<Role, User> _userManager;
public LogInManager(
UserManager userManager,
IMultiTenancyConfig multiTenancyConfig,
IRepository<Tenant> tenantRepository,
IUnitOfWorkManager unitOfWorkManager,
ISettingManager settingManager,
IRepository<UserLoginAttempt, long> userLoginAttemptRepository,
IUserManagementConfig userManagementConfig,
IIocResolver iocResolver,
IPasswordHasher<User> passwordHasher,
RoleManager roleManager,
UserClaimsPrincipalFactory claimsPrincipalFactory,
UserStore userStore)
: base(
userManager,
multiTenancyConfig,
tenantRepository,
unitOfWorkManager,
settingManager,
userLoginAttemptRepository,
userManagementConfig,
iocResolver,
passwordHasher,
roleManager,
claimsPrincipalFactory)
{
_userStore = userStore;
_userManager = userManager;
}
/// <summary>
/// Custom login implementation
/// </summary>
/// <param name="account">Username, phone number, or ID number</param>
/// <param name="password">Plain text password</param>
/// <returns>Login result</returns>
[UnitOfWork]
public virtual async Task<AbpLoginResult<Tenant, User>> LoginCustomAsync(string account, string password)
{
var result = await LoginCustomAsyncInternal(account, password);
// Record login attempt
await SaveLoginAttemptAsync(result, null, account);
return result;
}
protected virtual async Task<AbpLoginResult<Tenant, User>> LoginCustomAsyncInternal(string account, string password)
{
if (account.IsNullOrEmpty() || password.IsNullOrEmpty())
{
throw new ArgumentException("account or password");
}
// Retrieve default tenant if multi-tenancy is disabled
Tenant tenant = await GetDefaultTenantAsync();
int? tenantId = tenant?.Id;
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
// Fetch user based on account
var user = await _userStore.FindByAccountAsync(account);
if (user == null)
{
return new AbpLoginResult<Tenant, User>(AbpLoginResultType.UnknownExternalLogin, tenant);
}
// Validate password
var verificationResult = _userManager.PasswordHasher.VerifyHashedPassword(user, user.Password, password);
if (verificationResult != PasswordVerificationResult.Success)
{
if (await TryLockOutAsync(tenantId, user.Id))
{
return new AbpLoginResult<Tenant, User>(AbpLoginResultType.LockedOut, tenant, user);
}
return new AbpLoginResult<Tenant, User>(AbpLoginResultType.InvalidPassword, tenant, user);
}
// Reset failed login attempts
await _userManager.ResetAccessFailedCountAsync(user);
// Generate successful login result
return await CreateLoginResultAsync(user, tenant);
}
}
}
c、Web.Core Layer
Add method:
/// <summary>
/// Performs custom login
/// </summary>
/// <param name="userName">Account, ID, or phone number</param>
/// <param name="password">Plain text password</param>
/// <returns>Login result</returns>
private async Task<AbpLoginResult<Tenant, User>> GetCustomLoginResultAsync(string userName, string password)
{
var loginResult = await _logInManager.LoginCustomAsync(userName, password);
switch (loginResult.Result)
{
case AbpLoginResultType.Success:
return loginResult;
default:
throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(loginResult.Result, userName, null);
}
}
Refactoerd method:
[HttpPost]
public async Task<AuthenticateResultModel> Authenticate([FromBody] AuthenticateModel model)
{
//var loginResult = await GetLoginResultAsync(
// model.UserNameOrEmailAddress,
// model.Password,
// GetTenancyNameOrNull()
//);
// Custom login implementation
var loginResult = await GetCustomLoginResultAsync(
model.UserNameOrEmailAddress,
model.Password
);
var accessToken = CreateAccessToken(CreateJwtClaims(loginResult.Identity));
return new AuthenticateResultModel
{
AccessToken = accessToken,
EncryptedAccessToken = GetEncryptedAccessToken(accessToken),
ExpireInSeconds = (int)_configuration.Expiration.TotalSeconds,
UserId = loginResult.User.Id
};
}