Browse Source

Merge pull request #10570 from abpframework/maliming/AbpAuditHubFilter

Fix audit issues in Blazor Server.
pull/10608/head
Halil İbrahim Kalkan 5 years ago
committed by GitHub
parent
commit
d408fa0379
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs
  2. 26
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContext.cs
  3. 23
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContextAccessorHubFilter.cs
  4. 92
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AbpAuditHubFilter.cs
  5. 55
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AspNetCoreSignalRAuditLogContributor.cs
  6. 4
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs
  7. 23
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/DefaultAbpHubContextAccessor.cs
  8. 12
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/IAbpHubContextAccessor.cs
  9. 5
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs

12
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs

@ -8,6 +8,9 @@ using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.SignalR.Auditing;
using Volo.Abp.AspNetCore.SignalR.Authentication;
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Modularity;
@ -34,7 +37,9 @@ namespace Volo.Abp.AspNetCore.SignalR
var routePatterns = new List<string> {"/signalr-hubs"};
var signalRServerBuilder = context.Services.AddSignalR(options =>
{
options.AddFilter<AbpSignalRHubFilter>();
options.AddFilter<AbpHubContextAccessorHubFilter>();
options.AddFilter<AbpAuthenticationHubFilter>();
options.AddFilter<AbpAuditHubFilter>();
});
context.Services.ExecutePreConfiguredActions(signalRServerBuilder);
@ -75,6 +80,11 @@ namespace Volo.Abp.AspNetCore.SignalR
options.IgnoredUrls.AddIfNotContains(x => routePattern.StartsWith(x), () => routePattern);
}
});
Configure<AbpAuditingOptions>(options =>
{
options.Contributors.Add(new AspNetCoreSignalRAuditLogContributor());
});
}
private void AutoAddHubTypes(IServiceCollection services)

26
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContext.cs

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.AspNetCore.SignalR;
namespace Volo.Abp.AspNetCore.SignalR
{
public class AbpHubContext
{
public IServiceProvider ServiceProvider { get; }
public Hub Hub { get; }
public MethodInfo HubMethod { get; }
public IReadOnlyList<object> HubMethodArguments { get; }
public AbpHubContext(IServiceProvider serviceProvider, Hub hub, MethodInfo hubMethod, IReadOnlyList<object> hubMethodArguments)
{
ServiceProvider = serviceProvider;
Hub = hub;
HubMethod = hubMethod;
HubMethodArguments = hubMethodArguments;
}
}
}

23
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpHubContextAccessorHubFilter.cs

@ -0,0 +1,23 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.AspNetCore.SignalR
{
public class AbpHubContextAccessorHubFilter : IHubFilter
{
public virtual async ValueTask<object> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
{
var hubContextAccessor = invocationContext.ServiceProvider.GetRequiredService<IAbpHubContextAccessor>();
using (hubContextAccessor.Change(new AbpHubContext(
invocationContext.ServiceProvider,
invocationContext.Hub,
invocationContext.HubMethod,
invocationContext.HubMethodArguments)))
{
return await next(invocationContext);
}
}
}
}

92
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AbpAuditHubFilter.cs

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Auditing;
using Volo.Abp.Uow;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.SignalR.Auditing
{
public class AbpAuditHubFilter : IHubFilter
{
public virtual async ValueTask<object> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
{
var options = invocationContext.ServiceProvider.GetRequiredService<IOptions<AbpAuditingOptions>>().Value;
if (!options.IsEnabled)
{
return await next(invocationContext);
}
var hasError = false;
var auditingManager = invocationContext.ServiceProvider.GetRequiredService<IAuditingManager>();
using (var saveHandle = auditingManager.BeginScope())
{
Debug.Assert(auditingManager.Current != null);
object result;
try
{
result = await next(invocationContext);
if (auditingManager.Current.Log.Exceptions.Any())
{
hasError = true;
}
}
catch (Exception ex)
{
hasError = true;
if (!auditingManager.Current.Log.Exceptions.Contains(ex))
{
auditingManager.Current.Log.Exceptions.Add(ex);
}
throw;
}
finally
{
if (ShouldWriteAuditLog(invocationContext.ServiceProvider, hasError))
{
var unitOfWorkManager = invocationContext.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
if (unitOfWorkManager.Current != null)
{
await unitOfWorkManager.Current.SaveChangesAsync();
}
await saveHandle.SaveAsync();
}
}
return result;
}
}
private bool ShouldWriteAuditLog(IServiceProvider serviceProvider, bool hasError)
{
var options = serviceProvider.GetRequiredService<IOptions<AbpAuditingOptions>>().Value;
if (options.AlwaysLogOnException && hasError)
{
return true;
}
if (!options.IsEnabledForAnonymousUsers && !serviceProvider.GetRequiredService<ICurrentUser>().IsAuthenticated)
{
return false;
}
var auditingManager = serviceProvider.GetRequiredService<IAuditingManager>();
if (auditingManager.Current == null ||
auditingManager.Current.Log.Actions.IsNullOrEmpty())
{
return false;
}
return true;
}
}
}

55
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Auditing/AspNetCoreSignalRAuditLogContributor.cs

@ -0,0 +1,55 @@
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.AspNetCore.WebClientInfo;
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.SignalR.Auditing
{
public class AspNetCoreSignalRAuditLogContributor : AuditLogContributor, ITransientDependency
{
public ILogger<AspNetCoreSignalRAuditLogContributor> Logger { get; set; }
public AspNetCoreSignalRAuditLogContributor()
{
Logger = NullLogger<AspNetCoreSignalRAuditLogContributor>.Instance;
}
public override void PreContribute(AuditLogContributionContext context)
{
var hubContext = context.ServiceProvider.GetRequiredService<IAbpHubContextAccessor>().Context;
if (hubContext == null)
{
return;
}
var clientInfoProvider = context.ServiceProvider.GetRequiredService<IWebClientInfoProvider>();
if (context.AuditInfo.ClientIpAddress == null)
{
context.AuditInfo.ClientIpAddress = clientInfoProvider.ClientIpAddress;
}
if (context.AuditInfo.BrowserInfo == null)
{
context.AuditInfo.BrowserInfo = clientInfoProvider.BrowserInfo;
}
//TODO: context.AuditInfo.ClientName
}
public override void PostContribute(AuditLogContributionContext context)
{
var hubContext = context.ServiceProvider.GetRequiredService<IAbpHubContextAccessor>().Context;
if (hubContext == null)
{
return;
}
var firstAction = context.AuditInfo.Actions.FirstOrDefault();
context.AuditInfo.Url = firstAction?.ServiceName + "." + firstAction?.MethodName;
context.AuditInfo.HttpStatusCode = null;
}
}
}

4
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalRHubFilter.cs → framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs

@ -4,9 +4,9 @@ using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.AspNetCore.SignalR
namespace Volo.Abp.AspNetCore.SignalR.Authentication
{
public class AbpSignalRHubFilter : IHubFilter
public class AbpAuthenticationHubFilter : IHubFilter
{
public virtual async ValueTask<object> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
{

23
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/DefaultAbpHubContextAccessor.cs

@ -0,0 +1,23 @@
using System;
using System.Threading;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.SignalR
{
public class DefaultAbpHubContextAccessor : IAbpHubContextAccessor, ISingletonDependency
{
public AbpHubContext Context => _currentHubContext.Value;
private readonly AsyncLocal<AbpHubContext> _currentHubContext = new AsyncLocal<AbpHubContext>();
public virtual IDisposable Change(AbpHubContext context)
{
var parent = Context;
_currentHubContext.Value = context;
return new DisposeAction(() =>
{
_currentHubContext.Value = parent;
});
}
}
}

12
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/IAbpHubContextAccessor.cs

@ -0,0 +1,12 @@
using System;
namespace Volo.Abp.AspNetCore.SignalR
{
public interface IAbpHubContextAccessor
{
AbpHubContext Context { get; }
IDisposable Change(AbpHubContext context);
}
}

5
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs

@ -26,6 +26,11 @@ namespace Volo.Abp.AspNetCore.Auditing
return;
}
if (httpContext.WebSockets.IsWebSocketRequest)
{
return;
}
if (context.AuditInfo.HttpMethod == null)
{
context.AuditInfo.HttpMethod = httpContext.Request.Method;

Loading…
Cancel
Save