Browse Source

Merge pull request #4810 from abpframework/maliming/UserSecurityLog-patch

Use IdentitySecurityLogManager instead EventBus to save security logs.
pull/4882/head
Halil İbrahim Kalkan 6 years ago
committed by GitHub
parent
commit
f0d2a5151c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs
  2. 2
      modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLogoutModel.cs
  3. 16
      modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs
  4. 3
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs
  5. 6
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs
  6. 2
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs
  7. 9
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogContext.cs
  8. 26
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogManager.cs
  9. 19
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogActionConsts.cs
  10. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogIdentityConsts.cs
  11. 25
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs
  12. 37
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/SignInResultExtensions.cs

2
modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs

@ -132,7 +132,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
true true
); );
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{ {
Identity = IdentitySecurityLogIdentityConsts.Identity, Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = result.ToIdentitySecurityLogAction(), Action = result.ToIdentitySecurityLogAction(),

2
modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLogoutModel.cs

@ -20,7 +20,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
public override async Task<IActionResult> OnGetAsync() public override async Task<IActionResult> OnGetAsync()
{ {
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{ {
Identity = IdentitySecurityLogIdentityConsts.Identity, Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = IdentitySecurityLogActionConsts.Logout Action = IdentitySecurityLogActionConsts.Logout

16
modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs

@ -6,10 +6,8 @@ using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Settings; using Volo.Abp.Account.Settings;
using Volo.Abp.Account.Web.Areas.Account.Controllers.Models; using Volo.Abp.Account.Web.Areas.Account.Controllers.Models;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.Identity.AspNetCore; using Volo.Abp.Identity.AspNetCore;
using Volo.Abp.SecurityLog;
using Volo.Abp.Settings; using Volo.Abp.Settings;
using Volo.Abp.Validation; using Volo.Abp.Validation;
using SignInResult = Microsoft.AspNetCore.Identity.SignInResult; using SignInResult = Microsoft.AspNetCore.Identity.SignInResult;
@ -28,22 +26,20 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
protected SignInManager<IdentityUser> SignInManager { get; } protected SignInManager<IdentityUser> SignInManager { get; }
protected IdentityUserManager UserManager { get; } protected IdentityUserManager UserManager { get; }
protected ISettingProvider SettingProvider { get; } protected ISettingProvider SettingProvider { get; }
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }
protected ILocalEventBus LocalEventBus { get; }
public AccountController( public AccountController(
SignInManager<IdentityUser> signInManager, SignInManager<IdentityUser> signInManager,
IdentityUserManager userManager, IdentityUserManager userManager,
ISettingProvider settingProvider, ISettingProvider settingProvider,
ISecurityLogManager securityLogManager, IdentitySecurityLogManager identitySecurityLogManager)
ILocalEventBus localEventBus)
{ {
LocalizationResource = typeof(AccountResource); LocalizationResource = typeof(AccountResource);
SignInManager = signInManager; SignInManager = signInManager;
UserManager = userManager; UserManager = userManager;
SettingProvider = settingProvider; SettingProvider = settingProvider;
LocalEventBus = localEventBus; IdentitySecurityLogManager = identitySecurityLogManager;
} }
[HttpPost] [HttpPost]
@ -62,7 +58,7 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
true true
); );
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{ {
Identity = IdentitySecurityLogIdentityConsts.Identity, Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = signInResult.ToIdentitySecurityLogAction(), Action = signInResult.ToIdentitySecurityLogAction(),
@ -76,13 +72,13 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
[Route("logout")] [Route("logout")]
public virtual async Task Logout() public virtual async Task Logout()
{ {
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{ {
Identity = IdentitySecurityLogIdentityConsts.Identity, Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = IdentitySecurityLogActionConsts.Logout Action = IdentitySecurityLogActionConsts.Logout
}); });
await SignInManager.SignOutAsync(); await SignInManager.SignOutAsync();
} }
[HttpPost] [HttpPost]

3
modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs

@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Account.Localization; using Volo.Abp.Account.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using IdentityUser = Volo.Abp.Identity.IdentityUser; using IdentityUser = Volo.Abp.Identity.IdentityUser;
@ -15,7 +14,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
{ {
public SignInManager<IdentityUser> SignInManager { get; set; } public SignInManager<IdentityUser> SignInManager { get; set; }
public IdentityUserManager UserManager { get; set; } public IdentityUserManager UserManager { get; set; }
public ILocalEventBus LocalEventBus { get; set; } public IdentitySecurityLogManager IdentitySecurityLogManager { get; set; }
protected AccountPageModel() protected AccountPageModel()
{ {

6
modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs

@ -98,7 +98,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
true true
); );
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{ {
Identity = IdentitySecurityLogIdentityConsts.Identity, Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = result.ToIdentitySecurityLogAction(), Action = result.ToIdentitySecurityLogAction(),
@ -194,7 +194,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
if (!result.Succeeded) if (!result.Succeeded)
{ {
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{ {
Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
Action = "Login" + result Action = "Login" + result
@ -224,7 +224,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
await SignInManager.SignInAsync(user, false); await SignInManager.SignInAsync(user, false);
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{ {
Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
Action = result.ToIdentitySecurityLogAction(), Action = result.ToIdentitySecurityLogAction(),

2
modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs

@ -16,7 +16,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
public virtual async Task<IActionResult> OnGetAsync() public virtual async Task<IActionResult> OnGetAsync()
{ {
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{ {
Identity = IdentitySecurityLogIdentityConsts.Identity, Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = IdentitySecurityLogActionConsts.Logout Action = IdentitySecurityLogActionConsts.Logout

9
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogEvent.cs → modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogContext.cs

@ -1,13 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity namespace Volo.Abp.Identity
{ {
public class IdentitySecurityLogEvent : IMultiTenant public class IdentitySecurityLogContext
{ {
public Guid? TenantId { get; set; }
public string Identity { get; set; } public string Identity { get; set; }
public string Action { get; set; } public string Action { get; set; }
@ -18,12 +15,12 @@ namespace Volo.Abp.Identity
public Dictionary<string, object> ExtraProperties { get; } public Dictionary<string, object> ExtraProperties { get; }
public IdentitySecurityLogEvent() public IdentitySecurityLogContext()
{ {
ExtraProperties = new Dictionary<string, object>(); ExtraProperties = new Dictionary<string, object>();
} }
public virtual IdentitySecurityLogEvent WithProperty(string key, object value) public virtual IdentitySecurityLogContext WithProperty(string key, object value)
{ {
ExtraProperties[key] = value; ExtraProperties[key] = value;
return this; return this;

26
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogHandler.cs → modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogManager.cs

@ -2,15 +2,13 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus;
using Volo.Abp.Security.Claims; using Volo.Abp.Security.Claims;
using Volo.Abp.SecurityLog; using Volo.Abp.SecurityLog;
using Volo.Abp.Uow;
using Volo.Abp.Users; using Volo.Abp.Users;
namespace Volo.Abp.Identity namespace Volo.Abp.Identity
{ {
public class IdentitySecurityLogHandler : ILocalEventHandler<IdentitySecurityLogEvent>, ITransientDependency public class IdentitySecurityLogManager : ITransientDependency
{ {
protected ISecurityLogManager SecurityLogManager { get; } protected ISecurityLogManager SecurityLogManager { get; }
protected IdentityUserManager UserManager { get; } protected IdentityUserManager UserManager { get; }
@ -18,7 +16,7 @@ namespace Volo.Abp.Identity
protected IUserClaimsPrincipalFactory<IdentityUser> UserClaimsPrincipalFactory { get; } protected IUserClaimsPrincipalFactory<IdentityUser> UserClaimsPrincipalFactory { get; }
protected ICurrentUser CurrentUser { get; } protected ICurrentUser CurrentUser { get; }
public IdentitySecurityLogHandler( public IdentitySecurityLogManager(
ISecurityLogManager securityLogManager, ISecurityLogManager securityLogManager,
IdentityUserManager userManager, IdentityUserManager userManager,
ICurrentPrincipalAccessor currentPrincipalAccessor, ICurrentPrincipalAccessor currentPrincipalAccessor,
@ -32,24 +30,24 @@ namespace Volo.Abp.Identity
CurrentUser = currentUser; CurrentUser = currentUser;
} }
public async Task HandleEventAsync(IdentitySecurityLogEvent eventData) public async Task SaveAsync(IdentitySecurityLogContext context)
{ {
Action<SecurityLogInfo> securityLogAction = securityLog => Action<SecurityLogInfo> securityLogAction = securityLog =>
{ {
securityLog.Identity = eventData.Identity; securityLog.Identity = context.Identity;
securityLog.Action = eventData.Action; securityLog.Action = context.Action;
if (securityLog.UserName.IsNullOrWhiteSpace()) if (!context.UserName.IsNullOrWhiteSpace())
{ {
securityLog.UserName = eventData.UserName; securityLog.UserName = context.UserName;
} }
if (securityLog.ClientId.IsNullOrWhiteSpace()) if (!context.ClientId.IsNullOrWhiteSpace())
{ {
securityLog.ClientId = eventData.ClientId; securityLog.ClientId = context.ClientId;
} }
foreach (var property in eventData.ExtraProperties) foreach (var property in context.ExtraProperties)
{ {
securityLog.ExtraProperties[property.Key] = property.Value; securityLog.ExtraProperties[property.Key] = property.Value;
} }
@ -61,13 +59,13 @@ namespace Volo.Abp.Identity
} }
else else
{ {
if (eventData.UserName.IsNullOrWhiteSpace()) if (context.UserName.IsNullOrWhiteSpace())
{ {
await SecurityLogManager.SaveAsync(securityLogAction); await SecurityLogManager.SaveAsync(securityLogAction);
} }
else else
{ {
var user = await UserManager.FindByNameAsync(eventData.UserName); var user = await UserManager.FindByNameAsync(context.UserName);
if (user != null) if (user != null)
{ {
using (CurrentPrincipalAccessor.Change(await UserClaimsPrincipalFactory.CreateAsync(user))) using (CurrentPrincipalAccessor.Change(await UserClaimsPrincipalFactory.CreateAsync(user)))

19
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogActionConsts.cs

@ -0,0 +1,19 @@
namespace Volo.Abp.IdentityServer
{
public class IdentityServerSecurityLogActionConsts
{
public static string LoginSucceeded { get; set; } = "LoginSucceeded";
public static string LoginLockedout { get; set; } = "LoginLockedout";
public static string LoginNotAllowed { get; set; } = "LoginNotAllowed";
public static string LoginRequiresTwoFactor { get; set; } = "LoginRequiresTwoFactor";
public static string LoginFailed { get; set; } = "LoginFailed";
public static string LoginInvalidUserName { get; set; } = "LoginInvalidUserName";
public static string LoginInvalidUserNameOrPassword { get; set; } = "LoginInvalidUserNameOrPassword";
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogIdentityConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer
{
public class IdentityServerSecurityLogIdentityConsts
{
public static string IdentityServer { get; set; } = "IdentityServer";
}
}

25
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs

@ -10,6 +10,7 @@ using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Localization; using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Security.Claims; using Volo.Abp.Security.Claims;
using Volo.Abp.Uow; using Volo.Abp.Uow;
@ -23,18 +24,21 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity
protected SignInManager<IdentityUser> SignInManager { get; } protected SignInManager<IdentityUser> SignInManager { get; }
protected IEventService Events { get; } protected IEventService Events { get; }
protected UserManager<IdentityUser> UserManager { get; } protected UserManager<IdentityUser> UserManager { get; }
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }
protected ILogger<ResourceOwnerPasswordValidator<IdentityUser>> Logger { get; } protected ILogger<ResourceOwnerPasswordValidator<IdentityUser>> Logger { get; }
protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; } protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; }
public AbpResourceOwnerPasswordValidator( public AbpResourceOwnerPasswordValidator(
UserManager<IdentityUser> userManager, UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager, SignInManager<IdentityUser> signInManager,
IdentitySecurityLogManager identitySecurityLogManager,
IEventService events, IEventService events,
ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger, ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger,
IStringLocalizer<AbpIdentityServerResource> localizer) IStringLocalizer<AbpIdentityServerResource> localizer)
{ {
UserManager = userManager; UserManager = userManager;
SignInManager = signInManager; SignInManager = signInManager;
IdentitySecurityLogManager = identitySecurityLogManager;
Events = events; Events = events;
Logger = logger; Logger = logger;
Localizer = localizer; Localizer = localizer;
@ -71,6 +75,12 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity
additionalClaims.ToArray() additionalClaims.ToArray()
); );
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
Action = result.ToIdentitySecurityLogAction(),
});
return; return;
} }
else if (result.IsLockedOut) else if (result.IsLockedOut)
@ -91,12 +101,25 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity
await Events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "invalid credentials", interactive: false)); await Events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "invalid credentials", interactive: false));
errorDescription = Localizer["InvalidUserNameOrPassword"]; errorDescription = Localizer["InvalidUserNameOrPassword"];
} }
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
Action = result.ToIdentitySecurityLogAction(),
UserName = context.UserName
});
} }
else else
{ {
Logger.LogInformation("No user found matching username: {username}", context.UserName); Logger.LogInformation("No user found matching username: {username}", context.UserName);
await Events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "invalid username", interactive: false)); await Events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "invalid username", interactive: false));
errorDescription = Localizer["InvalidUsername"]; errorDescription = Localizer["InvalidUsername"];
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
Action = IdentityServerSecurityLogActionConsts.LoginInvalidUserName
});
} }
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, errorDescription); context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, errorDescription);

37
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/SignInResultExtensions.cs

@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Identity;
namespace Volo.Abp.IdentityServer.AspNetIdentity
{
public static class SignInResultExtensions
{
public static string ToIdentitySecurityLogAction(this SignInResult result)
{
if (result.Succeeded)
{
return IdentityServerSecurityLogActionConsts.LoginSucceeded;
}
if (result.IsLockedOut)
{
return IdentityServerSecurityLogActionConsts.LoginLockedout;
}
if (result.RequiresTwoFactor)
{
return IdentityServerSecurityLogActionConsts.LoginRequiresTwoFactor;
}
if (result.IsNotAllowed)
{
return IdentityServerSecurityLogActionConsts.LoginNotAllowed;
}
if (!result.Succeeded)
{
return IdentityServerSecurityLogActionConsts.LoginFailed;
}
return IdentityServerSecurityLogActionConsts.LoginFailed;
}
}
}
Loading…
Cancel
Save