mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
started adding route authorisation
This commit is contained in:
parent
cb4b000b21
commit
0221ee9ccb
@ -4,5 +4,7 @@ echo Building Ocelot
|
|||||||
dotnet restore src/Ocelot
|
dotnet restore src/Ocelot
|
||||||
dotnet build src/Ocelot
|
dotnet build src/Ocelot
|
||||||
dotnet publish src/Ocelot -o artifacts/
|
dotnet publish src/Ocelot -o artifacts/
|
||||||
|
dotnet pack src/Ocelot/project.json --output nupkgs/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
53
src/Ocelot/Authorisation/AuthorisationMiddleware.cs
Normal file
53
src/Ocelot/Authorisation/AuthorisationMiddleware.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Ocelot.DownstreamRouteFinder;
|
||||||
|
using Ocelot.Errors;
|
||||||
|
using Ocelot.Middleware;
|
||||||
|
using Ocelot.ScopedData;
|
||||||
|
|
||||||
|
namespace Ocelot.Authorisation
|
||||||
|
{
|
||||||
|
public class AuthorisationMiddleware : OcelotMiddleware
|
||||||
|
{
|
||||||
|
private readonly RequestDelegate _next;
|
||||||
|
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
||||||
|
private readonly IAuthoriser _authoriser;
|
||||||
|
|
||||||
|
public AuthorisationMiddleware(RequestDelegate next,
|
||||||
|
IScopedRequestDataRepository scopedRequestDataRepository,
|
||||||
|
IAuthoriser authoriser)
|
||||||
|
: base(scopedRequestDataRepository)
|
||||||
|
{
|
||||||
|
_next = next;
|
||||||
|
_scopedRequestDataRepository = scopedRequestDataRepository;
|
||||||
|
_authoriser = authoriser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Invoke(HttpContext context)
|
||||||
|
{
|
||||||
|
var downstreamRoute = _scopedRequestDataRepository.Get<DownstreamRoute>("DownstreamRoute");
|
||||||
|
|
||||||
|
if (downstreamRoute.IsError)
|
||||||
|
{
|
||||||
|
SetPipelineError(downstreamRoute.Errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var authorised = _authoriser.Authorise(context.User, new RouteClaimsRequirement());
|
||||||
|
|
||||||
|
if (authorised)
|
||||||
|
{
|
||||||
|
await _next.Invoke(context);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//set an error
|
||||||
|
SetPipelineError(new List<Error>
|
||||||
|
{
|
||||||
|
new UnauthorisedError($"{context.User.Identity.Name} unable to access {downstreamRoute.Data.ReRoute.UpstreamTemplate}")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
|
||||||
|
namespace Ocelot.Authorisation
|
||||||
|
{
|
||||||
|
public static class AuthorisationMiddlewareMiddlewareExtensions
|
||||||
|
{
|
||||||
|
public static IApplicationBuilder UseAuthorisationMiddleware(this IApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
return builder.UseMiddleware<AuthorisationMiddleware>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
src/Ocelot/Authorisation/ClaimsAuthoriser.cs
Normal file
12
src/Ocelot/Authorisation/ClaimsAuthoriser.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.Security.Claims;
|
||||||
|
|
||||||
|
namespace Ocelot.Authorisation
|
||||||
|
{
|
||||||
|
public class ClaimsAuthoriser : IAuthoriser
|
||||||
|
{
|
||||||
|
public bool Authorise(ClaimsPrincipal claimsPrincipal, RouteClaimsRequirement routeClaimsRequirement)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/Ocelot/Authorisation/IAuthoriser.cs
Normal file
10
src/Ocelot/Authorisation/IAuthoriser.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System.Security.Claims;
|
||||||
|
|
||||||
|
namespace Ocelot.Authorisation
|
||||||
|
{
|
||||||
|
public interface IAuthoriser
|
||||||
|
{
|
||||||
|
bool Authorise(ClaimsPrincipal claimsPrincipal,
|
||||||
|
RouteClaimsRequirement routeClaimsRequirement);
|
||||||
|
}
|
||||||
|
}
|
11
src/Ocelot/Authorisation/RouteClaimsRequirement.cs
Normal file
11
src/Ocelot/Authorisation/RouteClaimsRequirement.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ocelot.Authorisation
|
||||||
|
{
|
||||||
|
public class RouteClaimsRequirement
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
12
src/Ocelot/Authorisation/UnauthorisedError.cs
Normal file
12
src/Ocelot/Authorisation/UnauthorisedError.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Ocelot.Errors;
|
||||||
|
|
||||||
|
namespace Ocelot.Authorisation
|
||||||
|
{
|
||||||
|
public class UnauthorisedError : Error
|
||||||
|
{
|
||||||
|
public UnauthorisedError(string message)
|
||||||
|
: base(message, OcelotErrorCode.UnauthorizedError)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Ocelot.Authentication.Handler.Creator;
|
using Ocelot.Authentication.Handler.Creator;
|
||||||
using Ocelot.Authentication.Handler.Factory;
|
using Ocelot.Authentication.Handler.Factory;
|
||||||
|
using Ocelot.Authorisation;
|
||||||
using Ocelot.Configuration.Creator;
|
using Ocelot.Configuration.Creator;
|
||||||
using Ocelot.Configuration.Parser;
|
using Ocelot.Configuration.Parser;
|
||||||
using Ocelot.Configuration.Provider;
|
using Ocelot.Configuration.Provider;
|
||||||
@ -45,6 +47,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
services.AddLogging();
|
services.AddLogging();
|
||||||
|
|
||||||
// ocelot services.
|
// ocelot services.
|
||||||
|
services.AddSingleton<IAuthoriser, ClaimsAuthoriser>();
|
||||||
services.AddSingleton<IAddHeadersToRequest, AddHeadersToRequest>();
|
services.AddSingleton<IAddHeadersToRequest, AddHeadersToRequest>();
|
||||||
services.AddSingleton<IClaimsParser, ClaimsParser>();
|
services.AddSingleton<IClaimsParser, ClaimsParser>();
|
||||||
services.AddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
|
services.AddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
CannotFindClaimError,
|
CannotFindClaimError,
|
||||||
ParsingConfigurationHeaderError,
|
ParsingConfigurationHeaderError,
|
||||||
NoInstructionsError,
|
NoInstructionsError,
|
||||||
InstructionNotForClaimsError
|
InstructionNotForClaimsError,
|
||||||
|
UnauthorizedError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Ocelot.Authentication.Middleware;
|
using Ocelot.Authentication.Middleware;
|
||||||
|
using Ocelot.Authorisation;
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||||
using Ocelot.DownstreamUrlCreator.Middleware;
|
using Ocelot.DownstreamUrlCreator.Middleware;
|
||||||
using Ocelot.HeaderBuilder.Middleware;
|
using Ocelot.HeaderBuilder.Middleware;
|
||||||
@ -19,6 +20,8 @@ namespace Ocelot.Middleware
|
|||||||
|
|
||||||
builder.UseAuthenticationMiddleware();
|
builder.UseAuthenticationMiddleware();
|
||||||
|
|
||||||
|
//builder.UseAuthorisationMiddleware();
|
||||||
|
|
||||||
builder.UseHttpRequestHeadersBuilderMiddleware();
|
builder.UseHttpRequestHeadersBuilderMiddleware();
|
||||||
|
|
||||||
builder.UseDownstreamUrlCreatorMiddleware();
|
builder.UseDownstreamUrlCreatorMiddleware();
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Authorisation;
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
|
using Ocelot.DownstreamRouteFinder;
|
||||||
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
|
using Ocelot.Responses;
|
||||||
|
using Ocelot.ScopedData;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Authorization
|
||||||
|
{
|
||||||
|
public class AuthorizationMiddlewareTests : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Mock<IScopedRequestDataRepository> _scopedRepository;
|
||||||
|
private readonly Mock<IAuthoriser> _authService;
|
||||||
|
private readonly string _url;
|
||||||
|
private readonly TestServer _server;
|
||||||
|
private readonly HttpClient _client;
|
||||||
|
private HttpResponseMessage _result;
|
||||||
|
private OkResponse<DownstreamRoute> _downstreamRoute;
|
||||||
|
|
||||||
|
public AuthorizationMiddlewareTests()
|
||||||
|
{
|
||||||
|
_url = "http://localhost:51879";
|
||||||
|
_scopedRepository = new Mock<IScopedRequestDataRepository>();
|
||||||
|
_authService = new Mock<IAuthoriser>();
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.ConfigureServices(x =>
|
||||||
|
{
|
||||||
|
x.AddSingleton(_authService.Object);
|
||||||
|
x.AddSingleton(_scopedRepository.Object);
|
||||||
|
})
|
||||||
|
.UseUrls(_url)
|
||||||
|
.UseKestrel()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseIISIntegration()
|
||||||
|
.UseUrls(_url)
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseAuthorisationMiddleware();
|
||||||
|
});
|
||||||
|
|
||||||
|
_server = new TestServer(builder);
|
||||||
|
_client = _server.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void happy_path()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().Build())))
|
||||||
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
|
.Then(x => x.ThenTheAuthServiceIsCalledCorrectly())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheAuthServiceIsCalledCorrectly()
|
||||||
|
{
|
||||||
|
_authService
|
||||||
|
.Verify(x => x.Authorise(It.IsAny<ClaimsPrincipal>(),
|
||||||
|
It.IsAny<RouteClaimsRequirement>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
|
{
|
||||||
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
|
_scopedRepository
|
||||||
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
|
.Returns(_downstreamRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenICallTheMiddleware()
|
||||||
|
{
|
||||||
|
_result = _client.GetAsync(_url).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_client.Dispose();
|
||||||
|
_server.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user