- Fixed BasicAuthenticationAttribute.
- All attributes now reside in Microsoft.AspNetCore.Mvc.Filters namespace.
This commit is contained in:
@@ -5,29 +5,16 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AMWD.Common.AspNetCore.BasicAuthentication;
|
using AMWD.Common.AspNetCore.BasicAuthentication;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace AMWD.Common.AspNetCore.Attributes
|
namespace Microsoft.AspNetCore.Mvc.Filters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A basic authentication as attribute to use for specific actions.
|
/// A basic authentication as attribute to use for specific actions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BasicAuthenticationAttribute : ActionFilterAttribute
|
public class BasicAuthenticationAttribute : ActionFilterAttribute
|
||||||
{
|
{
|
||||||
private readonly IServiceScopeFactory serviceScopeFactory;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="BasicAuthenticationAttribute"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="serviceScopeFactory">A service scope factory.</param>
|
|
||||||
public BasicAuthenticationAttribute(IServiceScopeFactory serviceScopeFactory)
|
|
||||||
{
|
|
||||||
this.serviceScopeFactory = serviceScopeFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a username to validate.
|
/// Gets or sets a username to validate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -61,9 +48,7 @@ namespace AMWD.Common.AspNetCore.Attributes
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var scope = serviceScopeFactory.CreateScope();
|
var logger = context.HttpContext.RequestServices.GetService<ILogger<BasicAuthenticationAttribute>>();
|
||||||
var logger = scope.ServiceProvider.GetService<ILogger<BasicAuthenticationAttribute>>();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var authHeader = AuthenticationHeaderValue.Parse(context.HttpContext.Request.Headers["Authorization"]);
|
var authHeader = AuthenticationHeaderValue.Parse(context.HttpContext.Request.Headers["Authorization"]);
|
||||||
@@ -77,7 +62,7 @@ namespace AMWD.Common.AspNetCore.Attributes
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var validator = scope.ServiceProvider.GetService<IBasicAuthenticationValidator>();
|
var validator = context.HttpContext.RequestServices.GetService<IBasicAuthenticationValidator>();
|
||||||
var principal = await validator?.ValidateAsync(credentials.First(), credentials.Last(), context.HttpContext.GetRemoteIpAddress());
|
var principal = await validator?.ValidateAsync(credentials.First(), credentials.Last(), context.HttpContext.GetRemoteIpAddress());
|
||||||
if (principal == null)
|
if (principal == null)
|
||||||
SetAuthenticateRequest(context);
|
SetAuthenticateRequest(context);
|
||||||
|
|||||||
@@ -3,14 +3,34 @@ using System.Collections.Generic;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.Filters
|
namespace Microsoft.AspNetCore.Mvc.Filters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Custom filter attribute to use Google's reCaptcha (v3).
|
/// Custom filter attribute to use Google's reCaptcha (v3).
|
||||||
|
/// <br/>
|
||||||
/// Usage: [ServiceFilter(typeof(GoogleReCaptchaAttribute))]
|
/// Usage: [ServiceFilter(typeof(GoogleReCaptchaAttribute))]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// appsettings.json:
|
||||||
|
/// <br/>
|
||||||
|
/// <code>
|
||||||
|
/// {<br/>
|
||||||
|
/// [...]<br/>
|
||||||
|
/// "Google": {<br/>
|
||||||
|
/// "ReCaptcha": {<br/>
|
||||||
|
/// "PrivateKey": "__private reCaptcha key__",<br/>
|
||||||
|
/// "PublicKey": "__public reCaptcha key__"<br/>
|
||||||
|
/// }<br/>
|
||||||
|
/// }<br/>
|
||||||
|
/// }
|
||||||
|
/// </code>
|
||||||
|
/// <br/>
|
||||||
|
/// The score from google can be found on HttpContext.Items[GoogleReCaptchaAttribute.ScoreKey].
|
||||||
|
/// </remarks>
|
||||||
|
|
||||||
public class GoogleReCaptchaAttribute : ActionFilterAttribute
|
public class GoogleReCaptchaAttribute : ActionFilterAttribute
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -30,33 +50,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters
|
|||||||
|
|
||||||
private const string VerificationUrl = "https://www.google.com/recaptcha/api/siteverify";
|
private const string VerificationUrl = "https://www.google.com/recaptcha/api/siteverify";
|
||||||
|
|
||||||
private readonly string privateKey;
|
private string privateKey;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="GoogleReCaptchaAttribute"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// appsettings.json:
|
|
||||||
/// <br/>
|
|
||||||
/// <code>
|
|
||||||
/// {<br/>
|
|
||||||
/// [...]<br/>
|
|
||||||
/// "Google": {<br/>
|
|
||||||
/// "ReCaptcha": {<br/>
|
|
||||||
/// "PrivateKey": "__private reCaptcha key__",<br/>
|
|
||||||
/// "PublicKey": "__public reCaptcha key__"<br/>
|
|
||||||
/// }<br/>
|
|
||||||
/// }<br/>
|
|
||||||
/// }
|
|
||||||
/// </code>
|
|
||||||
/// <br/>
|
|
||||||
/// The score from google can be found on HttpContext.Items[GoogleReCaptchaAttribute.ScoreKey].
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="configuration">The application configuration.</param>
|
|
||||||
public GoogleReCaptchaAttribute(IConfiguration configuration)
|
|
||||||
{
|
|
||||||
privateKey = configuration.GetValue<string>("Google:ReCaptcha:PrivateKey");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes the validattion in background.
|
/// Executes the validattion in background.
|
||||||
@@ -66,15 +60,18 @@ namespace Microsoft.AspNetCore.Mvc.Filters
|
|||||||
/// <returns>An awaitable task.</returns>
|
/// <returns>An awaitable task.</returns>
|
||||||
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||||
{
|
{
|
||||||
|
var configuration = context.HttpContext.RequestServices.GetService<IConfiguration>();
|
||||||
|
privateKey = configuration?.GetValue<string>("Google:ReCaptcha:PrivateKey");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(privateKey))
|
||||||
|
return;
|
||||||
|
|
||||||
await DoValidation(context);
|
await DoValidation(context);
|
||||||
await base.OnActionExecutionAsync(context, next);
|
await base.OnActionExecutionAsync(context, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DoValidation(ActionExecutingContext context)
|
private async Task DoValidation(ActionExecutingContext context)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(privateKey))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!context.HttpContext.Request.HasFormContentType)
|
if (!context.HttpContext.Request.HasFormContentType)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,10 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.HttpOverrides;
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace AMWD.Common.AspNetCore.Attributes
|
namespace Microsoft.AspNetCore.Mvc.Filters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implements an IP filter. The defined addresses are blocked.
|
/// Implements an IP filter. The defined addresses are blocked.
|
||||||
@@ -43,6 +41,7 @@ namespace AMWD.Common.AspNetCore.Attributes
|
|||||||
public override void OnActionExecuting(ActionExecutingContext context)
|
public override void OnActionExecuting(ActionExecutingContext context)
|
||||||
{
|
{
|
||||||
base.OnActionExecuting(context);
|
base.OnActionExecuting(context);
|
||||||
|
context.HttpContext.Items["RemoteAddress"] = context.HttpContext.GetRemoteIpAddress();
|
||||||
|
|
||||||
if (!RestrictLocalAccess && context.HttpContext.IsLocalRequest())
|
if (!RestrictLocalAccess && context.HttpContext.IsLocalRequest())
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,12 +2,10 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.HttpOverrides;
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace AMWD.Common.AspNetCore.Attributes
|
namespace Microsoft.AspNetCore.Mvc.Filters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implements an IP filter. Only defined addresses are allowed to access.
|
/// Implements an IP filter. Only defined addresses are allowed to access.
|
||||||
@@ -43,6 +41,7 @@ namespace AMWD.Common.AspNetCore.Attributes
|
|||||||
public override void OnActionExecuting(ActionExecutingContext context)
|
public override void OnActionExecuting(ActionExecutingContext context)
|
||||||
{
|
{
|
||||||
base.OnActionExecuting(context);
|
base.OnActionExecuting(context);
|
||||||
|
context.HttpContext.Items["RemoteAddress"] = context.HttpContext.GetRemoteIpAddress();
|
||||||
|
|
||||||
if (AllowLocalAccess && context.HttpContext.IsLocalRequest())
|
if (AllowLocalAccess && context.HttpContext.IsLocalRequest())
|
||||||
return;
|
return;
|
||||||
|
|||||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -4,10 +4,18 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased](https://git.am-wd.de/AM.WD/common/compare/v1.5.3...master) - 0000-00-00
|
## [Unreleased](https://git.am-wd.de/AM.WD/common/compare/v1.6.0...master) - 0000-00-00
|
||||||
_nothing changed yet_
|
_nothing changed yet_
|
||||||
|
|
||||||
|
|
||||||
|
## [v1.6.0](https://git.am-wd.de/AM.WD/common/compare/v1.5.3...v1.6.0) - 2022-06-22
|
||||||
|
### Fixed
|
||||||
|
- Fixed `BasicAuthenticationAttribute`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- All attributes now reside in `Microsoft.AspNetCore.Mvc.Filters` namespace.
|
||||||
|
|
||||||
|
|
||||||
## [v1.5.3](https://git.am-wd.de/AM.WD/common/compare/v1.5.2...v1.5.3) - 2022-06-22
|
## [v1.5.3](https://git.am-wd.de/AM.WD/common/compare/v1.5.2...v1.5.3) - 2022-06-22
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed problem with `ForbidResult` without having an authentication schema defined.
|
- Fixed problem with `ForbidResult` without having an authentication schema defined.
|
||||||
|
|||||||
Reference in New Issue
Block a user