使用 AspNetBoilerplate。我被要求创建一种方法来让用户在密码检查之前取消订阅服务,这就是我遇到的问题。
[AbpAuthorize]
public class UserCompaniesManagerAppService : InvoiceAppServiceBase, IApplicationService
{
public async Task CancelSubscription(CheckPasswordDto input)
{
using (CurrentUnitOfWork.SetTenantId(AbpSession.TenantId))
{
var user = await GetCurrentUserAsync();
//verify pass
if (await UserManager.CheckPasswordAsync(user, input.Password))
{
await UserManager.ResetAccessFailedCountAsync(user);
//TODO: unsubscribe
}
else
{
//response from server when wrong password
await UserManager.AccessFailedAsync(user);
var count = await UserManager.GetAccessFailedCountAsync(user);
var maxAttempts = await SettingManager.GetSettingValueAsync<int>(
AbpZeroSettingNames.UserManagement.UserLockOut.MaxFailedAccessAttemptsBeforeLockout);
throw new UserFriendlyException("tried " + count.ToString() + " left attempts " + (maxAttempts - count).ToString());
}
}
}
我正在使用文档中建议的“UserFriendlyException”。我期待看到输入错误密码的次数以及输入正确密码的次数。服务器以这种方式响应。
{
"result": null,
"targetUrl": null,
"success": false,
"error": {
"code": 0,
"message": "tried 1 left attempts 2",
"details": null,
"validationErrors": null
},
"unAuthorizedRequest": false,
"__abp": true
}
事实是,如果我继续执行它,它就会保持这些值。此外,数据库不计算失败的尝试。没有数据写入 AbpUsers 表。
我已经尝试使用,以防万一,
Task<string>
并以这种方式返回消息并且它工作正常,计数器,AbpUsers 中的字段和锁定。但我知道这不应该以这种方式完成,而是提供一个对象作为像 throw 这样的响应。
ABP 的常规工作单元 围绕您的 App Service 方法限定范围
CancelSubscription
:
如果没有抛出异常,它会在它结束时提交事务。如果抛出异常,它会回滚所有内容。
开始一个新的工作单元
uow
已完成:
using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
{
await UserManager.AccessFailedAsync(user);
uow.Complete();
}
var count = await UserManager.GetAccessFailedCountAsync(user);
var maxAttempts = await SettingManager.GetSettingValueAsync<int>(
AbpZeroSettingNames.UserManagement.UserLockOut.MaxFailedAccessAttemptsBeforeLockout);
//response from server when wrong password
throw new UserFriendlyException("tried " + count.ToString() + " left attempts " + (maxAttempts - count).ToString());
或者,您可以制作
AccessFailedAsync
virtual
并用 UnitOfWork
属性标记它:
[UnitOfWork(TransactionScopeOption.RequiresNew)]
public virtual async Task AccessFailedAsync(User user)
{
// ...
}