mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 20:12:51 +08:00
commit to move to my back after hacking around at work..this is not simple :(
This commit is contained in:
parent
120532bb0d
commit
fd9eae0152
@ -1,7 +1,9 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using IdentityServer4.AccessTokenValidation;
|
||||||
using IdentityServer4.Extensions;
|
using IdentityServer4.Extensions;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Builder;
|
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");
|
_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()}");
|
_logger.LogError($"Error getting authentication handler for {context.Request.Path}. {authenticationHandler.Errors.ToErrorString()}");
|
||||||
SetPipelineError(authenticationHandler.Errors);
|
SetPipelineError(authenticationHandler.Errors);
|
||||||
return;
|
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)
|
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()}");
|
_logger.LogError($"Client has NOT been authenticated for {context.Request.Path} and pipeline error set. {error.ToErrorString()}");
|
||||||
SetPipelineError(error);
|
SetPipelineError(error);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//todo - remove the scheme or do we leave it?
|
||||||
|
auth.RemoveScheme(DownstreamRoute.ReRoute.AuthenticationOptions.Provider);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -124,7 +148,7 @@ namespace Ocelot.Authentication.Middleware
|
|||||||
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
|
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||||
{
|
{
|
||||||
var principal = new ClaimsPrincipal();
|
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));
|
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, Scheme.Name, ClaimValueTypes.String, Scheme.Name));
|
||||||
if (Options.Instance != null)
|
if (Options.Instance != null)
|
||||||
{
|
{
|
||||||
|
@ -44,6 +44,7 @@ using System.Net.Http;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using IdentityServer4.AccessTokenValidation;
|
using IdentityServer4.AccessTokenValidation;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
@ -149,6 +150,27 @@ namespace Ocelot.DependencyInjection
|
|||||||
{
|
{
|
||||||
services.AddIdentityServer(identityServerConfiguration, configurationRoot);
|
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;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user