mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 20:10:50 +08:00 
			
		
		
		
	started adding authentication stack, thing that decides if we should be authenticated is in
This commit is contained in:
		@@ -0,0 +1,11 @@
 | 
			
		||||
namespace Ocelot.Library.Infrastructure.Authentication
 | 
			
		||||
{
 | 
			
		||||
    using Responses;
 | 
			
		||||
    public class CouldNotFindConfigurationError : Error
 | 
			
		||||
    {
 | 
			
		||||
        public CouldNotFindConfigurationError(string message) 
 | 
			
		||||
            : base(message)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,10 @@
 | 
			
		||||
namespace Ocelot.Library.Infrastructure.Authentication
 | 
			
		||||
{
 | 
			
		||||
    using DownstreamRouteFinder;
 | 
			
		||||
    using Responses;
 | 
			
		||||
 | 
			
		||||
    public interface IRouteRequiresAuthentication
 | 
			
		||||
    {
 | 
			
		||||
        Response<bool> IsAuthenticated(DownstreamRoute downstreamRoute, string httpMethod);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,35 @@
 | 
			
		||||
namespace Ocelot.Library.Infrastructure.Authentication
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.Linq;
 | 
			
		||||
    using Configuration;
 | 
			
		||||
    using DownstreamRouteFinder;
 | 
			
		||||
    using Responses;
 | 
			
		||||
 | 
			
		||||
    public class RouteRequiresAuthentication : IRouteRequiresAuthentication
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IOcelotConfiguration _configuration;
 | 
			
		||||
 | 
			
		||||
        public RouteRequiresAuthentication(IOcelotConfiguration configuration)
 | 
			
		||||
        {
 | 
			
		||||
            _configuration = configuration;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Response<bool> IsAuthenticated(DownstreamRoute downstreamRoute, string httpMethod)
 | 
			
		||||
        {
 | 
			
		||||
            var reRoute =
 | 
			
		||||
                _configuration.ReRoutes.FirstOrDefault(
 | 
			
		||||
                    x =>
 | 
			
		||||
                        x.DownstreamTemplate == downstreamRoute.DownstreamUrlTemplate &&
 | 
			
		||||
                        string.Equals(x.UpstreamHttpMethod, httpMethod, StringComparison.CurrentCultureIgnoreCase));
 | 
			
		||||
 | 
			
		||||
            if (reRoute == null)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<bool>(new List<Error> {new CouldNotFindConfigurationError($"Could not find configuration for {downstreamRoute.DownstreamUrlTemplate} using method {httpMethod}")});
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new OkResponse<bool>(reRoute.IsAuthenticated);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -43,7 +43,9 @@ namespace Ocelot.Library.Infrastructure.Configuration
 | 
			
		||||
 | 
			
		||||
                upstreamTemplate = $"{upstreamTemplate}{RegExMatchEndString}";
 | 
			
		||||
 | 
			
		||||
                _reRoutes.Add(new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, reRoute.UpstreamHttpMethod, upstreamTemplate));
 | 
			
		||||
                var isAuthenticated = !string.IsNullOrEmpty(reRoute.Authentication);
 | 
			
		||||
 | 
			
		||||
                _reRoutes.Add(new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated));
 | 
			
		||||
            }   
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,17 +2,19 @@
 | 
			
		||||
{
 | 
			
		||||
    public class ReRoute
 | 
			
		||||
    {
 | 
			
		||||
        public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern)
 | 
			
		||||
        public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern, bool isAuthenticated)
 | 
			
		||||
        {
 | 
			
		||||
            DownstreamTemplate = downstreamTemplate;
 | 
			
		||||
            UpstreamTemplate = upstreamTemplate;
 | 
			
		||||
            UpstreamHttpMethod = upstreamHttpMethod;
 | 
			
		||||
            UpstreamTemplatePattern = upstreamTemplatePattern;
 | 
			
		||||
            IsAuthenticated = isAuthenticated;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string DownstreamTemplate { get; private set; }
 | 
			
		||||
        public string UpstreamTemplate { get; private set; }
 | 
			
		||||
        public string UpstreamTemplatePattern { get; private set; }
 | 
			
		||||
        public string UpstreamHttpMethod { get; private set; }
 | 
			
		||||
        public bool IsAuthenticated { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -5,5 +5,6 @@
 | 
			
		||||
        public string DownstreamTemplate { get; set; }
 | 
			
		||||
        public string UpstreamTemplate { get; set; }
 | 
			
		||||
        public string UpstreamHttpMethod { get; set; }
 | 
			
		||||
        public string Authentication { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								src/Ocelot.Library/Middleware/AuthenticationMiddleware.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/Ocelot.Library/Middleware/AuthenticationMiddleware.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
namespace Ocelot.Library.Middleware
 | 
			
		||||
{
 | 
			
		||||
    using System.Threading.Tasks;
 | 
			
		||||
    using Infrastructure.Authentication;
 | 
			
		||||
    using Infrastructure.DownstreamRouteFinder;
 | 
			
		||||
    using Infrastructure.Repository;
 | 
			
		||||
    using Infrastructure.Responses;
 | 
			
		||||
    using Microsoft.AspNetCore.Http;
 | 
			
		||||
 | 
			
		||||
    public class AuthenticationMiddleware : OcelotMiddleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly RequestDelegate _next;
 | 
			
		||||
        private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
 | 
			
		||||
        private readonly IRouteRequiresAuthentication _requiresAuthentication;
 | 
			
		||||
        public AuthenticationMiddleware(RequestDelegate next, 
 | 
			
		||||
            IScopedRequestDataRepository scopedRequestDataRepository, 
 | 
			
		||||
            IRouteRequiresAuthentication requiresAuthentication) 
 | 
			
		||||
            : base(scopedRequestDataRepository)
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _scopedRequestDataRepository = scopedRequestDataRepository;
 | 
			
		||||
            _requiresAuthentication = requiresAuthentication;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(HttpContext context)
 | 
			
		||||
        {
 | 
			
		||||
            var downstreamRoute = _scopedRequestDataRepository.Get<DownstreamRoute>("DownstreamRoute");
 | 
			
		||||
 | 
			
		||||
            var isAuthenticated = _requiresAuthentication.IsAuthenticated(downstreamRoute.Data, context.Request.Method);
 | 
			
		||||
 | 
			
		||||
            if (isAuthenticated.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                SetPipelineError(downstreamRoute.Errors);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (IsAuthenticatedRoute(isAuthenticated))
 | 
			
		||||
            {
 | 
			
		||||
                //todo - build auth pipeline and then call normal pipeline if all good?
 | 
			
		||||
                await _next.Invoke(context);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                await _next.Invoke(context);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static bool IsAuthenticatedRoute(Response<bool> isAuthenticated)
 | 
			
		||||
        {
 | 
			
		||||
            return isAuthenticated.Data;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,12 @@
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Library.Middleware
 | 
			
		||||
{
 | 
			
		||||
    public static class AuthenticationMiddlewareMiddlewareExtensions
 | 
			
		||||
    {
 | 
			
		||||
        public static IApplicationBuilder UseAuthenticationMiddleware(this IApplicationBuilder builder)
 | 
			
		||||
        {
 | 
			
		||||
            return builder.UseMiddleware<AuthenticationMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -2,7 +2,6 @@ using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
 | 
			
		||||
using Ocelot.Library.Infrastructure.Repository;
 | 
			
		||||
using Ocelot.Library.Infrastructure.Responder;
 | 
			
		||||
using Ocelot.Library.Infrastructure.UrlTemplateReplacer;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Library.Middleware
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ namespace Ocelot.Library.Middleware
 | 
			
		||||
{
 | 
			
		||||
    public static class DownstreamUrlCreatorMiddlewareExtensions
 | 
			
		||||
    {
 | 
			
		||||
        public static IApplicationBuilder UserDownstreamUrlCreatorMiddleware(this IApplicationBuilder builder)
 | 
			
		||||
        public static IApplicationBuilder UseDownstreamUrlCreatorMiddleware(this IApplicationBuilder builder)
 | 
			
		||||
        {
 | 
			
		||||
            return builder.UseMiddleware<DownstreamUrlCreatorMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,8 @@ using Ocelot.Library.Middleware;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot
 | 
			
		||||
{
 | 
			
		||||
    using Library.Infrastructure.Authentication;
 | 
			
		||||
 | 
			
		||||
    public class Startup
 | 
			
		||||
    {
 | 
			
		||||
        public Startup(IHostingEnvironment env)
 | 
			
		||||
@@ -52,6 +54,7 @@ namespace Ocelot
 | 
			
		||||
            services.AddSingleton<IHttpRequester, HttpClientHttpRequester>();
 | 
			
		||||
            services.AddSingleton<IHttpResponder, HttpContextResponder>();
 | 
			
		||||
            services.AddSingleton<IRequestBuilder, HttpRequestBuilder>();
 | 
			
		||||
            services.AddSingleton<IRouteRequiresAuthentication, RouteRequiresAuthentication>();
 | 
			
		||||
 | 
			
		||||
            // see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc
 | 
			
		||||
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
 | 
			
		||||
@@ -69,7 +72,9 @@ namespace Ocelot
 | 
			
		||||
 | 
			
		||||
            app.UseDownstreamRouteFinderMiddleware();
 | 
			
		||||
 | 
			
		||||
            app.UserDownstreamUrlCreatorMiddleware();
 | 
			
		||||
            app.UseAuthenticationMiddleware();
 | 
			
		||||
 | 
			
		||||
            app.UseDownstreamUrlCreatorMiddleware();
 | 
			
		||||
 | 
			
		||||
            app.UseHttpRequestBuilderMiddleware();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user