mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-10-31 12:15:28 +08:00 
			
		
		
		
	commit to move to my back after hacking around at work..this is not simple :(
This commit is contained in:
		| @@ -1,7 +1,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Security.Claims; | ||||
| using System.Text.Encodings.Web; | ||||
| using System.Threading.Tasks; | ||||
| using IdentityServer4.AccessTokenValidation; | ||||
| using IdentityServer4.Extensions; | ||||
| using Microsoft.AspNetCore.Authentication; | ||||
| using Microsoft.AspNetCore.Builder; | ||||
| @@ -71,17 +73,37 @@ namespace Ocelot.Authentication.Middleware | ||||
|             { | ||||
|                 _logger.LogDebug($"{context.Request.Path} is an authenticated route. {MiddlewareName} checking if client is authenticated"); | ||||
|  | ||||
|                 var authenticationHandler = _authHandlerFactory.Get(_app, DownstreamRoute.ReRoute.AuthenticationOptions); | ||||
|                 //var authenticationHandler = _authHandlerFactory.Get(_app, DownstreamRoute.ReRoute.AuthenticationOptions); | ||||
|  | ||||
|                 if (authenticationHandler.IsError) | ||||
|                 /* if (authenticationHandler.IsError) | ||||
|                  { | ||||
|                      _logger.LogError($"Error getting authentication handler for {context.Request.Path}. {authenticationHandler.Errors.ToErrorString()}"); | ||||
|                      SetPipelineError(authenticationHandler.Errors); | ||||
|                      return; | ||||
|                  } | ||||
|  | ||||
|                 await authenticationHandler.Data.Handler.Handle(context); | ||||
|                  await authenticationHandler.Data.Handler.Handle(context);*/ | ||||
|  | ||||
|                 //todo - add the scheme for this route?? | ||||
|                 var auth = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>(); | ||||
|                  | ||||
|                 /*        Action<IdentityServerAuthenticationOptions> configureOptions = o => | ||||
|                         { | ||||
|                             o.Authority = ""; | ||||
|                             o.ApiName = ""; | ||||
|                             o.RequireHttpsMetadata = true; | ||||
|                             o.SupportedTokens = SupportedTokens.Both; | ||||
|                             o.ApiSecret = ""; | ||||
|                         }; | ||||
|                         */ | ||||
|              | ||||
|  | ||||
|                 //var scheme = new AuthenticationScheme(DownstreamRoute.ReRoute.AuthenticationOptions.Provider, DownstreamRoute.ReRoute.AuthenticationOptions.Provider, typeof(IdentityServerAuthenticationHandler)); | ||||
|                 //auth.AddScheme(scheme); | ||||
|  | ||||
|                 //todo - call the next middleware to authenticate? Does this need to be on a different branch so it doesnt call any further middlewares? | ||||
|                 var result = await context.AuthenticateAsync(DownstreamRoute.ReRoute.AuthenticationOptions.Provider); | ||||
|                 context.User = result.Principal; | ||||
|  | ||||
|                 if (context.User.Identity.IsAuthenticated) | ||||
|                 { | ||||
| @@ -98,8 +120,10 @@ namespace Ocelot.Authentication.Middleware | ||||
|  | ||||
|                     _logger.LogError($"Client has NOT been authenticated for {context.Request.Path} and pipeline error set. {error.ToErrorString()}"); | ||||
|                     SetPipelineError(error); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 //todo - remove the scheme or do we leave it? | ||||
|                 auth.RemoveScheme(DownstreamRoute.ReRoute.AuthenticationOptions.Provider); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @@ -124,7 +148,7 @@ namespace Ocelot.Authentication.Middleware | ||||
|         protected override Task<AuthenticateResult> HandleAuthenticateAsync() | ||||
|         { | ||||
|             var principal = new ClaimsPrincipal(); | ||||
|             var id = new ClaimsIdentity(); | ||||
|             var id = new ClaimsIdentity("Ocelot"); | ||||
|             id.AddClaim(new Claim(ClaimTypes.NameIdentifier, Scheme.Name, ClaimValueTypes.String, Scheme.Name)); | ||||
|             if (Options.Instance != null) | ||||
|             { | ||||
|   | ||||
| @@ -44,6 +44,7 @@ using System.Net.Http; | ||||
| using System.Reflection; | ||||
| using System.Security.Cryptography.X509Certificates; | ||||
| using IdentityServer4.AccessTokenValidation; | ||||
| using Microsoft.AspNetCore.Authentication; | ||||
| using Microsoft.AspNetCore.Builder; | ||||
| using Microsoft.AspNetCore.Hosting; | ||||
| using Microsoft.IdentityModel.Tokens; | ||||
| @@ -149,6 +150,27 @@ namespace Ocelot.DependencyInjection | ||||
|             { | ||||
|                 services.AddIdentityServer(identityServerConfiguration, configurationRoot); | ||||
|             } | ||||
|             services.AddSingleton(services); | ||||
|  | ||||
|  | ||||
|             Action<AuthenticationSchemeBuilder> builder = schemeBuilder => | ||||
|             { | ||||
|                  | ||||
|             }  | ||||
|  | ||||
|             services.AddAuthentication(x => | ||||
|                 { | ||||
|                     x.AddScheme("", ); | ||||
|                 }) | ||||
|                 .AddIdentityServerAuthentication(o => | ||||
|                 { | ||||
|                     o.Authority = "http://localhost:51888"; | ||||
|                     o.ApiName = "api"; | ||||
|                     o.RequireHttpsMetadata = false; | ||||
|                     o.SupportedTokens = SupportedTokens.Both; | ||||
|                     o.ApiSecret = "secret"; | ||||
|                 }); | ||||
|  | ||||
|  | ||||
|             return services; | ||||
|         } | ||||
|   | ||||
							
								
								
									
										121
									
								
								test/Ocelot.UnitTests/DynamicSchemeTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								test/Ocelot.UnitTests/DynamicSchemeTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | ||||
| // Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information. | ||||
|  | ||||
| using System; | ||||
| using System.Net; | ||||
| using System.Security.Claims; | ||||
| using System.Text.Encodings.Web; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Authentication; | ||||
| using Microsoft.AspNetCore.Authentication.Cookies; | ||||
| using Microsoft.AspNetCore.Builder; | ||||
| using Microsoft.AspNetCore.Hosting; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.TestHost; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Options; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Ocelot.UnitTests | ||||
| { | ||||
|     public class DynamicSchemeTests | ||||
|     { | ||||
|         [Fact] | ||||
|         public async Task OptionsAreConfiguredOnce() | ||||
|         { | ||||
|             var server = CreateServer(s => | ||||
|             { | ||||
|                 s.Configure<TestOptions>("One", o => o.Instance = new Singleton()); | ||||
|             }); | ||||
|             // Add One scheme | ||||
|             var response = await server.CreateClient().GetAsync("http://example.com/add/One"); | ||||
|             Assert.Equal(HttpStatusCode.OK, response.StatusCode); | ||||
|             var transaction = await server.CreateClient().GetAsync("http://example.com/auth/One"); | ||||
|             var result = await transaction.Content.ReadAsStringAsync(); | ||||
|             result.ShouldBe("True"); | ||||
|         } | ||||
|  | ||||
|         public class TestOptions : AuthenticationSchemeOptions | ||||
|         { | ||||
|             public Singleton Instance { get; set; } | ||||
|         } | ||||
|  | ||||
|         public class Singleton | ||||
|         { | ||||
|             public static int _count; | ||||
|  | ||||
|             public Singleton() | ||||
|             { | ||||
|                 _count++; | ||||
|                 Count = _count; | ||||
|             } | ||||
|  | ||||
|             public int Count { get; } | ||||
|         } | ||||
|  | ||||
|         private class TestHandler : AuthenticationHandler<TestOptions> | ||||
|         { | ||||
|             public TestHandler(IOptionsMonitor<TestOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) | ||||
|             { | ||||
|             } | ||||
|  | ||||
|             protected override Task<AuthenticateResult> HandleAuthenticateAsync() | ||||
|             { | ||||
|                 var principal = new ClaimsPrincipal(); | ||||
|                 var id = new ClaimsIdentity("Ocelot"); | ||||
|                 id.AddClaim(new Claim(ClaimTypes.NameIdentifier, Scheme.Name, ClaimValueTypes.String, Scheme.Name)); | ||||
|                 if (Options.Instance != null) | ||||
|                 { | ||||
|                     id.AddClaim(new Claim("Count", Options.Instance.Count.ToString())); | ||||
|                 } | ||||
|                 principal.AddIdentity(id); | ||||
|                 return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(principal, new AuthenticationProperties(), Scheme.Name))); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private static TestServer CreateServer(Action<IServiceCollection> configureServices = null) | ||||
|         { | ||||
|             var builder = new WebHostBuilder() | ||||
|                 .Configure(app => | ||||
|                 { | ||||
|                     app.UseAuthentication(); | ||||
|                     app.Use(async (context, next) => | ||||
|                     { | ||||
|                         var req = context.Request; | ||||
|                         var res = context.Response; | ||||
|                         if (req.Path.StartsWithSegments(new PathString("/add"), out var remainder)) | ||||
|                         { | ||||
|                             var name = remainder.Value.Substring(1); | ||||
|                             var auth = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>(); | ||||
|                             var scheme = new AuthenticationScheme(name, name, typeof(TestHandler)); | ||||
|                             auth.AddScheme(scheme); | ||||
|                         } | ||||
|                         else if (req.Path.StartsWithSegments(new PathString("/auth"), out remainder)) | ||||
|                         { | ||||
|                             var name = (remainder.Value.Length > 0) ? remainder.Value.Substring(1) : null; | ||||
|                             var result = await context.AuthenticateAsync(name); | ||||
|                             context.User = result.Principal; | ||||
|                             await res.WriteJsonAsync(context.User.Identity.IsAuthenticated.ToString()); | ||||
|                         } | ||||
|                         else if (req.Path.StartsWithSegments(new PathString("/remove"), out remainder)) | ||||
|                         { | ||||
|                             var name = remainder.Value.Substring(1); | ||||
|                             var auth = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>(); | ||||
|                             auth.RemoveScheme(name); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             await next(); | ||||
|                         } | ||||
|                     }); | ||||
|                 }) | ||||
|                 .ConfigureServices(services => | ||||
|                 { | ||||
|                     configureServices?.Invoke(services); | ||||
|                     services.AddAuthentication(); | ||||
|                 }); | ||||
|             return new TestServer(builder); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Tom Pallister
					Tom Pallister