Мне нужно создать простой сервис Netcore 2.2 (построенный как библиотека), который должен использовать базовый c auth. Файл проекта:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net462</TargetFramework>
<OutputType>Library</OutputType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<OutDir>$(SolutionDir)bin\$(Configuration)\Modules\WebDataExport</OutDir>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.ComponentModel.Composition" />
</ItemGroup>
</Project>
Строитель:
public IWebHost BuildWebHost(string[] args)
{
var path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
var config = new ConfigurationBuilder()
.SetBasePath(path)
.AddJsonFile("appsettings.json", optional: false)
.Build();
var webHost = WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext) =>
{
})
.ConfigureServices(services =>
{
services.AddMvcCore().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// configure basic authentication
services.AddAuthentication("BasicAuthentication")
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null);
// Add service for data access
services.AddSingleton(_dataProvider);
})
.Configure(app =>
{
app.UseAuthentication();
app.UseMvc();
})
.UseUrls($"http://*:{config.GetValue<int>("ListenPort")}")
.UseKestrel();
return webHost.Build();
}
И мой контроллер:
[Authorize]
[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class GetRecordingsController : ControllerBase
{
public GetRecordingsController(ILogger<GetRecordingsController> logger, IDataProvider dataProvider)
{
}
[HttpGet]
public async Task<IActionResult> Get([FromQuery] string From,
[FromQuery] string To)
{
}
}
И, в конце концов, это BasicAuthenticationHandler :
public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
private readonly IDataProvider _dataProvider;
public BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
IDataProvider dataProvider)
: base(options, logger, encoder, clock)
{
_dataProvider = dataProvider;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.ContainsKey("Authorization"))
return AuthenticateResult.Fail("Missing Authorization Header");
User user;
try
{
var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
var credentials = Encoding.UTF8.GetString(credentialBytes).Split(new[] { ':' }, 2);
var username = credentials[0];
var password = credentials[1];
user = await _dataProvider.AuthenticateUser(username, password);
}
catch
{
return AuthenticateResult.Fail("Invalid Authorization Header");
}
if (user == null)
return AuthenticateResult.Fail("Invalid Username or Password");
var claims = new[] {
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Username),
};
var identity = new ClaimsIdentity(claims, Scheme.Name);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return AuthenticateResult.Success(ticket);
}
}
Теперь, что происходит, если я посылаю GET с неверным паролем, HandleAuthenticateAsyn c правильно возвращает fail , но я получаю метод вызывается в любом случае: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService не вызывается.
Это журнал:
info: Sinora.Modules.WebDataExport.BasicAuthenticationHandler[7]
BasicAuthentication was not authenticated. Failure message: Invalid Username or Password
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'Sinora.Modules.WebDataExport.Controllers.GetRecordingsController.Get (Sinora.Modules.WebDataExport)'
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Route matched with {action = "Get", controller = "GetRecordings"}. Executing action Sinora.Modules.WebDataExport.Controllers.GetRecordingsController.Get (Sinora.Modules.WebDataExport)
.....
[METHOD EXECUTION]
.....
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'Sinora.Modules.WebDataExport.Controllers.GetRecordingsController.Get (Sinora.Modules.WebDataExport)'
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 11384.1282ms 200
Пока я ожидаю что-то вроде :
info: Sinora.Modules.WebDataExport.BasicAuthenticationHandler[7]
BasicAuthentication was not authenticated. Failure message: Invalid Username or Password
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'Sinora.Modules.WebDataExport.Controllers.GetRecordingsController.Get (Sinora.Modules.WebDataExport)'
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Route matched with {action = "Get", controller = "GetRecordings"}. Executing action Sinora.Modules.WebDataExport.Controllers.GetRecordingsController.Get (Sinora.Modules.WebDataExport)
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
Executing ChallengeResult with authentication schemes ().
info: WebApi.Helpers.BasicAuthenticationHandler[12]
AuthenticationScheme: BasicAuthentication was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action Sinora.Modules.WebDataExport.Controllers.GetRecordingsController.Get (Sinora.Modules.WebDataExport) in 11062.176ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'Sinora.Modules.WebDataExport.Controllers.GetRecordingsController.Get (Sinora.Modules.WebDataExport)'
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 11384.1282ms 200
Я не могу понять, где я не прав