private string CreateAccessToken(IEnumerable<Claim> claims, TokenValidationParameters validationParameters) { var now = DateTime.UtcNow; var expiration = TimeSpan.FromDays(7); var signingCredentials = new SigningCredentials(validationParameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256);
var jwtSecurityToken = new JwtSecurityToken( issuer: validationParameters.ValidIssuer, audience: validationParameters.ValidAudience, claims: claims, notBefore: now, expires: now.Add(expiration), signingCredentials: signingCredentials );
return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken); }
if (rememberClient) { if (await settingManager.GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.TwoFactorLogin.IsRememberBrowserEnabled)) { var expiration = TimeSpan.FromDays(7);
var tokenValidityKey = Guid.NewGuid().ToString("N"); var accessToken = CreateAccessToken(new[] { new Claim(USER_IDENTIFIER_CLAIM, user.ToUserIdentifier().ToString()), new Claim(REMEMBER_CLIENT_TOKEN, tokenValidityKey) }, validationParameters ); await _userManager.AddTokenValidityKeyAsync(user, tokenValidityKey, DateTime.Now.Add(expiration)); return accessToken; } }
public async Task<bool> TwoFactorClientRememberedAsync(UserIdentifier userIdentifier, string TwoFactorRememberClientToken, TokenValidationParameters validationParameters) { if (!await settingManager.GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.TwoFactorLogin.IsRememberBrowserEnabled)) { return false; }
if (string.IsNullOrWhiteSpace(TwoFactorRememberClientToken)) { return false; }
try { var tokenHandler = new JwtSecurityTokenHandler();
if (tokenHandler.CanReadToken(TwoFactorRememberClientToken)) { try { SecurityToken validatedToken; var principal = tokenHandler.ValidateToken(TwoFactorRememberClientToken, validationParameters, out validatedToken); var userIdentifierString = principal.Claims.First(c => c.Type == TwoFactorAuthorizationManager.USER_IDENTIFIER_CLAIM); if (userIdentifierString == null) { throw new SecurityTokenException(TwoFactorAuthorizationManager.USER_IDENTIFIER_CLAIM + " invalid"); }
var tokenValidityKeyInClaims = principal.Claims.First(c => c.Type == TwoFactorAuthorizationManager.REMEMBER_CLIENT_TOKEN);
var currentUserIdentifier = UserIdentifier.Parse(userIdentifierString.Value);
var user = _userManager.GetUserById(currentUserIdentifier.UserId); var isValidityKetValid = AsyncHelper.RunSync(() => _userManager.IsTokenValidityKeyValidAsync(user, tokenValidityKeyInClaims.Value));
if (!isValidityKetValid) { throw new SecurityTokenException(REMEMBER_CLIENT_TOKEN + " invalid");
public class TwoFactorAuthorizationManager : ITransientDependency { public const string USER_IDENTIFIER_CLAIM = "USER_IDENTIFIER_CLAIM"; public const string REMEMBER_CLIENT_TOKEN = "REMEMBER_CLIENT_TOKEN";
public async Task<bool> IsTwoFactorAuthRequiredAsync(AbpLoginResult<Tenant, User> loginResult, string TwoFactorRememberClientToken, TokenValidationParameters validationParameters) { if (!await settingManager.GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.TwoFactorLogin.IsEnabled)) { return false; }
if (!loginResult.User.IsTwoFactorEnabled) { return false; } if ((await _userManager.GetValidTwoFactorProvidersAsync(loginResult.User)).Count <= 0) { return false; }
if (await TwoFactorClientRememberedAsync(loginResult.User.ToUserIdentifier(), TwoFactorRememberClientToken, validationParameters)) { return false; }
return true; }
public async Task<bool> TwoFactorClientRememberedAsync(UserIdentifier userIdentifier, string TwoFactorRememberClientToken, TokenValidationParameters validationParameters) { if (!await settingManager.GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.TwoFactorLogin.IsRememberBrowserEnabled)) { return false; }
if (string.IsNullOrWhiteSpace(TwoFactorRememberClientToken)) { return false; }
try { var tokenHandler = new JwtSecurityTokenHandler();
if (tokenHandler.CanReadToken(TwoFactorRememberClientToken)) { try { SecurityToken validatedToken; var principal = tokenHandler.ValidateToken(TwoFactorRememberClientToken, validationParameters, out validatedToken); var userIdentifierString = principal.Claims.First(c => c.Type == TwoFactorAuthorizationManager.USER_IDENTIFIER_CLAIM); if (userIdentifierString == null) { throw new SecurityTokenException(TwoFactorAuthorizationManager.USER_IDENTIFIER_CLAIM + " invalid"); }
var tokenValidityKeyInClaims = principal.Claims.First(c => c.Type == TwoFactorAuthorizationManager.REMEMBER_CLIENT_TOKEN);
var currentUserIdentifier = UserIdentifier.Parse(userIdentifierString.Value);
var user = _userManager.GetUserById(currentUserIdentifier.UserId); var isValidityKetValid = AsyncHelper.RunSync(() => _userManager.IsTokenValidityKeyValidAsync(user, tokenValidityKeyInClaims.Value));
if (!isValidityKetValid) { throw new SecurityTokenException(REMEMBER_CLIENT_TOKEN + " invalid");
public async Task<string> TwoFactorAuthenticateAsync(User user, string token, string provider, bool rememberClient, TokenValidationParameters validationParameters) { if (provider == "Email") { var isValidate = await emailCaptchaManager.VerifyCaptchaAsync(token, CaptchaPurpose.TWO_FACTOR_AUTHORIZATION); if (!isValidate) { throw new UserFriendlyException("验证码错误"); } }
else if (provider == "Phone") { var isValidate = await smsCaptchaManager.VerifyCaptchaAsync(token, CaptchaPurpose.TWO_FACTOR_AUTHORIZATION); if (!isValidate) { throw new UserFriendlyException("验证码错误"); } } else { throw new UserFriendlyException("验证码提供者错误"); }
if (rememberClient) { if (await settingManager.GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.TwoFactorLogin.IsRememberBrowserEnabled)) { var expiration = TimeSpan.FromDays(7);
var tokenValidityKey = Guid.NewGuid().ToString("N"); var accessToken = CreateAccessToken(new[] { new Claim(USER_IDENTIFIER_CLAIM, user.ToUserIdentifier().ToString()), new Claim(REMEMBER_CLIENT_TOKEN, tokenValidityKey) }, validationParameters );
private string CreateAccessToken(IEnumerable<Claim> claims, TokenValidationParameters validationParameters) { var now = DateTime.UtcNow; var expiration = TimeSpan.FromDays(7); var signingCredentials = new SigningCredentials(validationParameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256);
var jwtSecurityToken = new JwtSecurityToken( issuer: validationParameters.ValidIssuer, audience: validationParameters.ValidAudience, claims: claims, notBefore: now, expires: now.Add(expiration), signingCredentials: signingCredentials );
return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken); }
public async Task SendCaptchaAsync(long userId, string provider) { var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) { throw new UserFriendlyException("找不到用户");
}
if (provider == "Email") { if (!user.IsEmailConfirmed) { throw new UserFriendlyException("未绑定邮箱"); } await emailCaptchaManager.SendCaptchaAsync(user.Id, user.EmailAddress, CaptchaPurpose.TWO_FACTOR_AUTHORIZATION); } else if (provider == "Phone") { if (!user.IsPhoneNumberConfirmed) { throw new UserFriendlyException("未绑定手机号"); } await smsCaptchaManager.SendCaptchaAsync(user.Id, user.PhoneNumber, CaptchaPurpose.TWO_FACTOR_AUTHORIZATION); } else { throw new UserFriendlyException("验证码提供者错误"); } }