简体   繁体   English

如何在 netcore 2.2 中使用 Basic Auth

[英]How to use Basic Auth in netcore 2.2

I have to build a simple netcore 2.2 service (built as library) which has to use basic auth.我必须构建一个简单的 netcore 2.2 服务(构建为库),它必须使用基本身份验证。
The project file is:项目文件是:

<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>

The Builder is:建造者是:

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();
}

And my controller:还有我的控制器:

[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)
    {
    }
}

And, in the end, this is the BasicAuthenticationHandler :最后,这是 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);
    }
}

Now, what's happen is that, if i send a GET with a wrong password, the HandleAuthenticateAsync correctly returns fail but my get method is called anyway: the Microsoft.AspNetCore.Authorization.DefaultAuthorizationService is not called.现在,发生的情况是,如果我使用错误的密码发送 GET,则 HandleAuthenticateAsync 会正确返回失败,但无论如何都会调用我的 get 方法:未调用Microsoft.AspNetCore.Authorization.DefaultAuthorizationService

This is the log:这是日志:

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

While I'm expecting something like:虽然我期待这样的事情:

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

I cannot figure out where I'm wrong我不知道我错在哪里

I think you are missing the following call in your startup file我认为您在启动文件中缺少以下调用

app.UseAuthorization();

I hope this solves your issue.我希望这能解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM