ABP登录返回错误次数、锁定时间
1 /// <summary>
2 /// 获取登录结果,如果错误则返回错误信息
3 /// </summary>
4 /// <param name="usernameOrEmailAddress"></param>
5 /// <param name="password"></param>
6 /// <param name="tenancyName"></param>
7 /// <returns></returns>
8 private async Task<AbpLoginResult<Tenant, User>> GetLoginResultAsync(string usernameOrEmailAddress, string password, string tenancyName)
9 {
10 var loginResult = await _logInManager.LoginAsync(usernameOrEmailAddress, password, tenancyName);
11 switch (loginResult.Result)
12 {
13 case AbpLoginResultType.Success:
14 return loginResult;
15 default:
16 {
17 throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(loginResult.Result, usernameOrEmailAddress, tenancyName, loginResult.User);
18 }
19 }
20 }
1 public Exception CreateExceptionForFailedLoginAttempt(AbpLoginResultType result, string usernameOrEmailAddress, string tenancyName, User user)
2 {
3 switch (result)
4 {
5 case AbpLoginResultType.Success:
6 return new Exception("Don't call this method with a success result!");
7 case AbpLoginResultType.InvalidUserNameOrEmailAddress:
8 case AbpLoginResultType.InvalidPassword:
9 //return new UserFriendlyException(L("LoginFailed"), L("InvalidUserNameOrPassword"));
10 return new UserFriendlyException(L("LoginFailed"), L("InvalidUserNameOrPasswordRemainErrorTimes{0}", 5 - user.AccessFailedCount));
11 case AbpLoginResultType.InvalidTenancyName:
12 return new UserFriendlyException(L("LoginFailed"), L("ThereIsNoTenantDefinedWithName{0}", tenancyName));
13 case AbpLoginResultType.TenantIsNotActive:
14 return new UserFriendlyException(L("LoginFailed"), L("TenantIsNotActive", tenancyName));
15 case AbpLoginResultType.UserIsNotActive:
16 return new UserFriendlyException(L("LoginFailed"), L("UserIsNotActiveAndCanNotLogin", usernameOrEmailAddress));
17 case AbpLoginResultType.UserEmailIsNotConfirmed:
18 return new UserFriendlyException(L("LoginFailed"), L("UserEmailIsNotConfirmedAndCanNotLogin"));
19 case AbpLoginResultType.LockedOut:
20 //todo 此处后期需要改为客户端获取UTC时间后,格式化展示,以符合国际化
21 return new UserFriendlyException(L("LoginFailed"), L("UserLockedOutMessageUntilTime{0}", user.LockoutEndDateUtc?.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")));
22 default: // Can not fall to default actually. But other result types can be added in the future and we may forget to handle it
23 Logger.Warn("Unhandled login fail reason: " + result);
24 return new UserFriendlyException(L("LoginFailed"));
25 }
26 }
var loginResult = await _logInManager.LoginAsync(usernameOrEmailAddress, password, tenancyName);
后,数据库就更新了。为了弄清楚原理只能去解读ABP源码了。
protected virtual async Task<bool> TryLockOutAsync(int? tenantId, long userId)
{
using (var uow = UnitOfWorkManager.Begin(TransactionScopeOption.Suppress))
{
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
var user = await UserManager.FindByIdAsync(userId.ToString()); (await UserManager.AccessFailedAsync(user)).CheckErrors(); var isLockOut = await UserManager.IsLockedOutAsync(user); await UnitOfWorkManager.Current.SaveChangesAsync(); await uow.CompleteAsync(); return isLockOut;
}
}
}
1 /// <summary>
2 /// Increments the access failed count for the user as an asynchronous operation.
3 /// If the failed access account is greater than or equal to the configured maximum number of attempts,
4 /// the user will be locked out for the configured lockout time span.
5 /// </summary>
6 /// <param name="user">The user whose failed access count to increment.</param>
7 /// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the operation.</returns>
8 public virtual async Task<IdentityResult> AccessFailedAsync(TUser user)
9 {
10 ThrowIfDisposed();
11 var store = GetUserLockoutStore();
12 if (user == null)
13 {
14 throw new ArgumentNullException(nameof(user));
15 }
16
17 // If this puts the user over the threshold for lockout, lock them out and reset the access failed count
18 var count = await store.IncrementAccessFailedCountAsync(user, CancellationToken);
19 if (count < Options.Lockout.MaxFailedAccessAttempts)
20 {
21 return await UpdateUserAsync(user);
22 }
23 Logger.LogWarning(12, "User is locked out.");
24 await store.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.Add(Options.Lockout.DefaultLockoutTimeSpan),
25 CancellationToken);
26 await store.ResetAccessFailedCountAsync(user, CancellationToken);
27 return await UpdateUserAsync(user);
28 }
会执行IncrementAccessFailedCountAsync和UpdateUserAsync。如果成功执行,user会增加一次验证失败的统计并保存到数据库中。
1 protected virtual async Task<AbpLoginResult<TTenant, TUser>> LoginAsyncInternal(string userNameOrEmailAddress, string plainPassword, string tenancyName, bool shouldLockout)
2 {
3 if (userNameOrEmailAddress.IsNullOrEmpty())
4 {
5 throw new ArgumentNullException(nameof(userNameOrEmailAddress));
6 }
7
8 if (plainPassword.IsNullOrEmpty())
9 {
10 throw new ArgumentNullException(nameof(plainPassword));
11 }
12
13 //Get and check tenant
14 TTenant tenant = null;
15 using (UnitOfWorkManager.Current.SetTenantId(null))
16 {
17 if (!MultiTenancyConfig.IsEnabled)
18 {
19 tenant = await GetDefaultTenantAsync();
20 }
21 else if (!string.IsNullOrWhiteSpace(tenancyName))
22 {
23 tenant = await TenantRepository.FirstOrDefaultAsync(t => t.TenancyName == tenancyName);
24 if (tenant == null)
25 {
26 return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.InvalidTenancyName);
27 }
28
29 if (!tenant.IsActive)
30 {
31 return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.TenantIsNotActive, tenant);
32 }
33 }
34 }
35
36 var tenantId = tenant == null ? (int?)null : tenant.Id;
37 using (UnitOfWorkManager.Current.SetTenantId(tenantId))
38 {
39 await UserManager.InitializeOptionsAsync(tenantId);
40
41 //TryLoginFromExternalAuthenticationSources method may create the user, that's why we are calling it before AbpUserStore.FindByNameOrEmailAsync
42 var loggedInFromExternalSource = await TryLoginFromExternalAuthenticationSourcesAsync(userNameOrEmailAddress, plainPassword, tenant);
43
44 var user = await UserManager.FindByNameOrEmailAsync(tenantId, userNameOrEmailAddress);
45 if (user == null)
46 {
47 return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.InvalidUserNameOrEmailAddress, tenant);
48 }
49
50 if (await UserManager.IsLockedOutAsync(user))
51 {
52 return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.LockedOut, tenant, user);
53 }
54
55 if (!loggedInFromExternalSource)
56 {
57 if (!await UserManager.CheckPasswordAsync(user, plainPassword))
58 {
59 if (shouldLockout)
60 {
61 if (await TryLockOutAsync(tenantId, user.Id))
62 {
63 return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.LockedOut, tenant, user);
64 }
65 }
66
67 return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.InvalidPassword, tenant, user);
68 }
69
70 await UserManager.ResetAccessFailedCountAsync(user);
71 }
72
73 return await CreateLoginResultAsync(user, tenant);
74 }
75 }
public class LogInManager : AbpLogInManager<Tenant, Role, User>
{
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)
: base(
userManager,
multiTenancyConfig,
tenantRepository,
unitOfWorkManager,
settingManager,
userLoginAttemptRepository,
userManagementConfig,
iocResolver,
passwordHasher,
roleManager,
claimsPrincipalFactory)
{
} protected override async Task<AbpLoginResult<Tenant, User>> LoginAsyncInternal(string userNameOrEmailAddress, string plainPassword, string tenancyName, bool shouldLockout)
{
//return base.LoginAsyncInternal(userNameOrEmailAddress, plainPassword, tenancyName, shouldLockout);
if (userNameOrEmailAddress.IsNullOrEmpty())
{
throw new ArgumentNullException(nameof(userNameOrEmailAddress));
} if (plainPassword.IsNullOrEmpty())
{
throw new ArgumentNullException(nameof(plainPassword));
} //Get and check tenant
Tenant tenant = null;
using (UnitOfWorkManager.Current.SetTenantId(null))
{
if (!MultiTenancyConfig.IsEnabled)
{
tenant = await GetDefaultTenantAsync();
}
else if (!string.IsNullOrWhiteSpace(tenancyName))
{
tenant = await TenantRepository.FirstOrDefaultAsync(t => t.TenancyName == tenancyName);
if (tenant == null)
{
return new AbpLoginResult<Tenant, User>(AbpLoginResultType.InvalidTenancyName);
} if (!tenant.IsActive)
{
return new AbpLoginResult<Tenant, User>(AbpLoginResultType.TenantIsNotActive, tenant);
}
}
} var tenantId = tenant == null ? (int?)null : tenant.Id;
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
await UserManager.InitializeOptionsAsync(tenantId); //TryLoginFromExternalAuthenticationSources method may create the user, that's why we are calling it before AbpUserStore.FindByNameOrEmailAsync
var loggedInFromExternalSource = await TryLoginFromExternalAuthenticationSourcesAsync(userNameOrEmailAddress, plainPassword, tenant); var user = await UserManager.FindByNameOrEmailAsync(tenantId, userNameOrEmailAddress);
if (user == null)
{
return new AbpLoginResult<Tenant, User>(AbpLoginResultType.InvalidUserNameOrEmailAddress, tenant);
} if (await UserManager.IsLockedOutAsync(user))
{
return new AbpLoginResult<Tenant, User>(AbpLoginResultType.LockedOut, tenant, user);
} if (!loggedInFromExternalSource)
{
if (!await UserManager.CheckPasswordAsync(user, plainPassword))
{
if (shouldLockout)
{
//此处返回修改后的结果,可能会对数据产生影响
if (await TryLockOutAsync(tenantId, user))
{
return new AbpLoginResult<Tenant, User>(AbpLoginResultType.LockedOut, tenant, user);
}
} return new AbpLoginResult<Tenant, User>(AbpLoginResultType.InvalidPassword, tenant, user);
} await UserManager.ResetAccessFailedCountAsync(user);
} return await CreateLoginResultAsync(user, tenant);
}
} /// <summary>
/// 尝试锁定用户,并更新其状态
/// </summary>
/// <param name="tenantId"></param>
/// <param name="inputUser"></param>
/// <returns></returns>
protected async Task<bool> TryLockOutAsync(int? tenantId, User inputUser)
{
using (var uow = UnitOfWorkManager.Begin(TransactionScopeOption.Suppress))
{
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
var user = await UserManager.FindByIdAsync(inputUser.Id.ToString()); (await UserManager.AccessFailedAsync(user)).CheckErrors(); var isLockOut = await UserManager.IsLockedOutAsync(user); await UnitOfWorkManager.Current.SaveChangesAsync(); await uow.CompleteAsync();
inputUser.AccessFailedCount = user.AccessFailedCount;
inputUser.LockoutEndDateUtc = user.LockoutEndDateUtc;
return isLockOut;
}
}
//return base.TryLockOutAsync(tenantId, userId);
}
}
ABP登录返回错误次数、锁定时间的更多相关文章
- Shiro+SpringMVC 实现更安全的登录(加密匹配&登录失败超次数锁定帐号)
原文:http://blog.csdn.net/wlwlwlwl015/article/details/48518003 前言 初学shiro,shiro提供了一系列安全相关的解决方案,根据官方的介绍 ...
- vmware vcenter orchestrator configuration提示“用户名密码错误或登录失败超过次数被锁定”
首次登录,使用默认用户密码登录vmware/vmware vmware vcenter orchestrator configuration提示"用户名密码错误或登录失败超过次数被锁定&qu ...
- asp.net限制用户登录错误次数
很经常在登录一个网站的时候看到,如果你登录的时候输入的账号密码错误超过三次就被锁定,然后等一段时间才能继续登录,最最经常使用的就是银行系统啦~~ 该功能处理流程如下: string uid = Req ...
- Linux使用pam_tally2.so模块限制登录失败锁定时间
关于PAM Linux-PAM (Pluggable Authentication Modules for Linux)可插拔认证模块. https://www.cnblogs.com/klb561/ ...
- DiscuzX2.5密码错误次数过多,请 15 分钟后重新登录的修改办法
source\function function_login.php $return = (!$login || (TIMESTAMP - $login['lastupdate'] > )) ? ...
- SpringBoot+SpringSecurity+Thymeleaf认证失败返回错误信息踩坑记录
Spring boot +Spring Security + Thymeleaf认证失败返回错误信息踩坑记录 步入8102年,现在企业开发追求快速,Springboot以多种优秀特性引领潮流,在众多使 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(15)-用户登录详细错误和权限数据库模型设计
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(15)-用户登录详细错误和权限数据库模型设计 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) ...
- python_login输入三次错误密码锁定密码_密码不允许为空
#!/usr/bin/env python #_*_coding:utf-8_*_ #by anthor zhangxiaoyu 2017-01-10 import getpass import os ...
- ADO之密码验证--3次错误就锁定『改进』
这里使用了SqlHelper,简化程序 自己写一个SqlHelper,把数据库的连接等都写到里面去. 首先把连接字符串添加到配置文件里去,右键解决方案-->添加新建项-->选择应用程序配置 ...
- Spring Security之多次登录失败后账户锁定功能的实现
在上一次写的文章中,为大家说到了如何动态的从数据库加载用户.角色.权限信息,从而实现登录验证及授权.在实际的开发过程中,我们通常会有这样的一个需求:当用户多次登录失败的时候,我们应该将账户锁定,等待一 ...
随机推荐
- C/C++实例汇集(1)
1.用代码判断一个系统是16位系统还是32位系统? 以下是几种常见编程语言中判断系统是 16 位还是 32 位的代码示例 C语言: #include <stdio.h> int main( ...
- Scrum 和我主张的管理方式的同与异
虽然零零星星接触过scrum的一些知识,之前并没有深入了解过.这次机缘巧合,将 Jeff Sutherland 的<用一半的时间做两倍的事>拜读完毕,感觉 scrum 的做法其实很多和我自 ...
- python 根据中文表头标题抓取动态(表格)文档数据
思路 如图左侧表头标题,要获得右侧数据.网页数据提取成汉字,表格数据间会有空格,用split()分隔成list.用index()查找某个汉字表头位置,输出list下一个位置既是要得到值 text2 = ...
- 报错test_features2d.cpp:51:10: fatal error: features2d/test/test_detectors_regression.impl.hpp: 没有那个文件
问题描述: ubuntu18.04安装opencv4.5.1+contrib 报错test_features2d.cpp:51:10: fatal error: features2d/test/tes ...
- SpringBoot集成swagger后出现: Failed to start bean ‘documentationPluginsBootstrapper‘的解决方法
SpringBoot集成swagger后出现: Failed to start bean 'documentationPluginsBootstrapper'的编译错误: org.springfram ...
- KMS for Windows 11
I. 镜像下载 Windows 镜像下载地址:站点1,站点2 II. 手动激活 参考文档:Easy ways to activate Windows 11 for FREE without a pro ...
- milvus基础
nlist和nprobe nlist 是调用 create_index 时设置的参数,nprobe 则是调用 search 时设置的参数. IVFLAT 和 SQ8 索引都是通过聚类算法把大量的向量划 ...
- 老奶奶看了都会的WSL2连接USB设备教程!
老奶奶看了都会的WSL2-Ubuntu连接USB设备教程! 作者:SkyXZ CSDN:SkyXZ--CSDN博客 博客园:SkyXZ - 博客园 参考资料:微软官方文档连接 USB 设备 | Mic ...
- nginx配置参数优化
ginx作为高性能web服务器,即使不特意调整配置参数也可以处理大量的并发请求.以下的配置参数是借鉴网上的一些调优参数,仅作为参考,不见得适于你的线上业务. worker进程 worker_proce ...
- 第一二章(Nginx+Lua)开发环境
第一章 安装OpenResty(Nginx+Lua)开发环境 首先我们选择使用OpenResty,其是由Nginx核心加很多第三方模块组成,其最大的亮点是默认集成了Lua开发环境,使得Nginx可以作 ...