[英]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.