Added protected ctor to AuthenticationSchemeProvider (#990)
This commit is contained in:
parent
51a7e83a23
commit
450900d14c
|
|
@ -15,13 +15,28 @@ namespace Microsoft.AspNetCore.Authentication
|
||||||
public class AuthenticationSchemeProvider : IAuthenticationSchemeProvider
|
public class AuthenticationSchemeProvider : IAuthenticationSchemeProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor.
|
/// Creates an instance of <see cref="AuthenticationSchemeProvider"/>
|
||||||
|
/// using the specified <paramref name="options"/>,
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="options">The <see cref="AuthenticationOptions"/> options.</param>
|
/// <param name="options">The <see cref="AuthenticationOptions"/> options.</param>
|
||||||
public AuthenticationSchemeProvider(IOptions<AuthenticationOptions> options)
|
public AuthenticationSchemeProvider(IOptions<AuthenticationOptions> options)
|
||||||
|
: this(options, new Dictionary<string, AuthenticationScheme>(StringComparer.Ordinal))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of <see cref="AuthenticationSchemeProvider"/>
|
||||||
|
/// using the specified <paramref name="options"/> and <paramref name="schemes"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">The <see cref="AuthenticationOptions"/> options.</param>
|
||||||
|
/// <param name="schemes">The dictionary used to store authentication schemes.</param>
|
||||||
|
protected AuthenticationSchemeProvider(IOptions<AuthenticationOptions> options, IDictionary<string, AuthenticationScheme> schemes)
|
||||||
{
|
{
|
||||||
_options = options.Value;
|
_options = options.Value;
|
||||||
|
|
||||||
|
_schemes = schemes ?? throw new ArgumentNullException(nameof(schemes));
|
||||||
|
_requestHandlers = new List<AuthenticationScheme>();
|
||||||
|
|
||||||
foreach (var builder in _options.Schemes)
|
foreach (var builder in _options.Schemes)
|
||||||
{
|
{
|
||||||
var scheme = builder.Build();
|
var scheme = builder.Build();
|
||||||
|
|
@ -32,8 +47,8 @@ namespace Microsoft.AspNetCore.Authentication
|
||||||
private readonly AuthenticationOptions _options;
|
private readonly AuthenticationOptions _options;
|
||||||
private readonly object _lock = new object();
|
private readonly object _lock = new object();
|
||||||
|
|
||||||
private IDictionary<string, AuthenticationScheme> _map = new Dictionary<string, AuthenticationScheme>(StringComparer.Ordinal);
|
private readonly IDictionary<string, AuthenticationScheme> _schemes;
|
||||||
private List<AuthenticationScheme> _requestHandlers = new List<AuthenticationScheme>();
|
private readonly List<AuthenticationScheme> _requestHandlers;
|
||||||
|
|
||||||
private Task<AuthenticationScheme> GetDefaultSchemeAsync()
|
private Task<AuthenticationScheme> GetDefaultSchemeAsync()
|
||||||
=> _options.DefaultScheme != null
|
=> _options.DefaultScheme != null
|
||||||
|
|
@ -101,7 +116,7 @@ namespace Microsoft.AspNetCore.Authentication
|
||||||
/// <param name="name">The name of the authenticationScheme.</param>
|
/// <param name="name">The name of the authenticationScheme.</param>
|
||||||
/// <returns>The scheme or null if not found.</returns>
|
/// <returns>The scheme or null if not found.</returns>
|
||||||
public virtual Task<AuthenticationScheme> GetSchemeAsync(string name)
|
public virtual Task<AuthenticationScheme> GetSchemeAsync(string name)
|
||||||
=> Task.FromResult(_map.ContainsKey(name) ? _map[name] : null);
|
=> Task.FromResult(_schemes.ContainsKey(name) ? _schemes[name] : null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the schemes in priority order for request handling.
|
/// Returns the schemes in priority order for request handling.
|
||||||
|
|
@ -116,13 +131,13 @@ namespace Microsoft.AspNetCore.Authentication
|
||||||
/// <param name="scheme">The scheme.</param>
|
/// <param name="scheme">The scheme.</param>
|
||||||
public virtual void AddScheme(AuthenticationScheme scheme)
|
public virtual void AddScheme(AuthenticationScheme scheme)
|
||||||
{
|
{
|
||||||
if (_map.ContainsKey(scheme.Name))
|
if (_schemes.ContainsKey(scheme.Name))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Scheme already exists: " + scheme.Name);
|
throw new InvalidOperationException("Scheme already exists: " + scheme.Name);
|
||||||
}
|
}
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
if (_map.ContainsKey(scheme.Name))
|
if (_schemes.ContainsKey(scheme.Name))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Scheme already exists: " + scheme.Name);
|
throw new InvalidOperationException("Scheme already exists: " + scheme.Name);
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +145,7 @@ namespace Microsoft.AspNetCore.Authentication
|
||||||
{
|
{
|
||||||
_requestHandlers.Add(scheme);
|
_requestHandlers.Add(scheme);
|
||||||
}
|
}
|
||||||
_map[scheme.Name] = scheme;
|
_schemes[scheme.Name] = scheme;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,22 +155,22 @@ namespace Microsoft.AspNetCore.Authentication
|
||||||
/// <param name="name">The name of the authenticationScheme being removed.</param>
|
/// <param name="name">The name of the authenticationScheme being removed.</param>
|
||||||
public virtual void RemoveScheme(string name)
|
public virtual void RemoveScheme(string name)
|
||||||
{
|
{
|
||||||
if (!_map.ContainsKey(name))
|
if (!_schemes.ContainsKey(name))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
if (_map.ContainsKey(name))
|
if (_schemes.ContainsKey(name))
|
||||||
{
|
{
|
||||||
var scheme = _map[name];
|
var scheme = _schemes[name];
|
||||||
_requestHandlers.Remove(scheme);
|
_requestHandlers.Remove(scheme);
|
||||||
_map.Remove(name);
|
_schemes.Remove(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync()
|
public virtual Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync()
|
||||||
=> Task.FromResult<IEnumerable<AuthenticationScheme>>(_map.Values);
|
=> Task.FromResult<IEnumerable<AuthenticationScheme>>(_schemes.Values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,10 +3,12 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Authentication
|
namespace Microsoft.AspNetCore.Authentication
|
||||||
|
|
@ -117,6 +119,39 @@ namespace Microsoft.AspNetCore.Authentication
|
||||||
Assert.NotNull(await provider.GetDefaultSignOutSchemeAsync());
|
Assert.NotNull(await provider.GetDefaultSignOutSchemeAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SchemeRegistrationIsCaseSensitive()
|
||||||
|
{
|
||||||
|
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||||
|
{
|
||||||
|
o.AddScheme<Handler>("signin", "whatever");
|
||||||
|
o.AddScheme<Handler>("signin", "whatever");
|
||||||
|
}).BuildServiceProvider();
|
||||||
|
|
||||||
|
var error = Assert.Throws<InvalidOperationException>(() => services.GetRequiredService<IAuthenticationSchemeProvider>());
|
||||||
|
|
||||||
|
Assert.Contains("Scheme already exists: signin", error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task LookupUsesProvidedStringComparer()
|
||||||
|
{
|
||||||
|
var services = new ServiceCollection().AddOptions()
|
||||||
|
.AddSingleton<IAuthenticationSchemeProvider, IgnoreCaseSchemeProvider>()
|
||||||
|
.AddAuthenticationCore(o => o.AddScheme<Handler>("signin", "whatever"))
|
||||||
|
.BuildServiceProvider();
|
||||||
|
|
||||||
|
var provider = services.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||||
|
|
||||||
|
var a = await provider.GetSchemeAsync("signin");
|
||||||
|
var b = await provider.GetSchemeAsync("SignIn");
|
||||||
|
var c = await provider.GetSchemeAsync("SIGNIN");
|
||||||
|
|
||||||
|
Assert.NotNull(a);
|
||||||
|
Assert.Same(a, b);
|
||||||
|
Assert.Same(b, c);
|
||||||
|
}
|
||||||
|
|
||||||
private class Handler : IAuthenticationHandler
|
private class Handler : IAuthenticationHandler
|
||||||
{
|
{
|
||||||
public Task<AuthenticateResult> AuthenticateAsync()
|
public Task<AuthenticateResult> AuthenticateAsync()
|
||||||
|
|
@ -160,5 +195,13 @@ namespace Microsoft.AspNetCore.Authentication
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class IgnoreCaseSchemeProvider : AuthenticationSchemeProvider
|
||||||
|
{
|
||||||
|
public IgnoreCaseSchemeProvider(IOptions<AuthenticationOptions> options)
|
||||||
|
: base(options, new Dictionary<string, AuthenticationScheme>(StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue