mirror of https://github.com/abpframework/abp.git
15 changed files with 173 additions and 21 deletions
@ -0,0 +1,57 @@ |
|||
using IdentityServer4.Services; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.IdentityServer.Clients; |
|||
|
|||
namespace Volo.Abp.IdentityServer |
|||
{ |
|||
public class AbpCorsPolicyService : ICorsPolicyService |
|||
{ |
|||
public ILogger<AbpCorsPolicyService> Logger { get; set; } |
|||
protected IHybridServiceScopeFactory HybridServiceScopeFactory { get; } |
|||
protected IDistributedCache<AllowedCorsOriginsCacheItem> Cache { get; } |
|||
|
|||
public AbpCorsPolicyService( |
|||
IDistributedCache<AllowedCorsOriginsCacheItem> cache, |
|||
IHybridServiceScopeFactory hybridServiceScopeFactory) |
|||
{ |
|||
Cache = cache; |
|||
HybridServiceScopeFactory = hybridServiceScopeFactory; |
|||
Logger = NullLogger<AbpCorsPolicyService>.Instance; |
|||
} |
|||
|
|||
public async Task<bool> IsOriginAllowedAsync(string origin) |
|||
{ |
|||
var cacheItem = await Cache.GetOrAddAsync(AllowedCorsOriginsCacheItem.AllOrigins, CreateCacheItemAsync); |
|||
|
|||
var isAllowed = cacheItem.AllowedOrigins.Contains(origin, StringComparer.OrdinalIgnoreCase); |
|||
|
|||
if (!isAllowed) |
|||
{ |
|||
Logger.LogWarning($"Origin is not allowed: {origin}"); |
|||
} |
|||
|
|||
return isAllowed; |
|||
} |
|||
|
|||
protected virtual async Task<AllowedCorsOriginsCacheItem> CreateCacheItemAsync() |
|||
{ |
|||
// doing this here and not in the ctor because: https://github.com/aspnet/AspNetCore/issues/2377
|
|||
using (var scope = HybridServiceScopeFactory.CreateScope()) |
|||
{ |
|||
var clientRepository = scope.ServiceProvider.GetRequiredService<IClientRepository>(); |
|||
|
|||
return new AllowedCorsOriginsCacheItem |
|||
{ |
|||
AllowedOrigins = (await clientRepository.GetAllDistinctAllowedCorsOriginsAsync()).ToArray() |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
namespace Volo.Abp.IdentityServer |
|||
{ |
|||
public class AllowedCorsOriginsCacheItem |
|||
{ |
|||
public const string AllOrigins = "AllOrigins"; |
|||
|
|||
public string[] AllowedOrigins { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Entities.Events; |
|||
using Volo.Abp.EventBus; |
|||
using Volo.Abp.IdentityServer.Clients; |
|||
|
|||
namespace Volo.Abp.IdentityServer |
|||
{ |
|||
public class AllowedCorsOriginsCacheItemInvalidator : ILocalEventHandler<EntityChangedEventData<Client>>, ITransientDependency |
|||
{ |
|||
protected IDistributedCache<AllowedCorsOriginsCacheItem> Cache { get; } |
|||
|
|||
public AllowedCorsOriginsCacheItemInvalidator(IDistributedCache<AllowedCorsOriginsCacheItem> cache) |
|||
{ |
|||
Cache = cache; |
|||
} |
|||
|
|||
public async Task HandleEventAsync(EntityChangedEventData<Client> eventData) |
|||
{ |
|||
await Cache.RemoveAsync(AllowedCorsOriginsCacheItem.AllOrigins); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace Volo.Abp.IdentityServer |
|||
{ |
|||
public class AbpIdentityServerDomainTestBase : AbpIntegratedTest<AbpIdentityServerDomainTestModule> |
|||
{ |
|||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|||
{ |
|||
options.UseAutofac(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
using System.Threading.Tasks; |
|||
using IdentityServer4.Services; |
|||
using Shouldly; |
|||
using Volo.Abp.IdentityServer.Clients; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.IdentityServer |
|||
{ |
|||
public class CorsPolicyService_Tests : AbpIdentityServerDomainTestBase |
|||
{ |
|||
private readonly ICorsPolicyService _corsPolicyService; |
|||
private readonly IClientRepository _clientRepository; |
|||
|
|||
public CorsPolicyService_Tests() |
|||
{ |
|||
_corsPolicyService = GetRequiredService<ICorsPolicyService>(); |
|||
_clientRepository = GetRequiredService<IClientRepository>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task IsOriginAllowedAsync() |
|||
{ |
|||
(await _corsPolicyService.IsOriginAllowedAsync("https://client1-origin.com")).ShouldBeTrue(); |
|||
(await _corsPolicyService.IsOriginAllowedAsync("https://unknown-origin.com")).ShouldBeFalse(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task IsOriginAllowedAsync_Should_Invalidate_Cache_On_Update() |
|||
{ |
|||
//It does not exists before
|
|||
(await _corsPolicyService.IsOriginAllowedAsync("https://new-origin.com")).ShouldBeFalse(); |
|||
|
|||
var client1 = await _clientRepository.FindByCliendIdAsync("ClientId1"); |
|||
client1.AddCorsOrigin("https://new-origin.com"); |
|||
await _clientRepository.UpdateAsync(client1); |
|||
|
|||
//It does exists now
|
|||
(await _corsPolicyService.IsOriginAllowedAsync("https://new-origin.com")).ShouldBeTrue(); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue