我正在开发一个 ASP.NET Core MVC 项目,最近向我的
Program.cs
文件添加了自定义授权服务:
执行此操作后,我在访问我的应用程序时遇到以下错误:
网址
https://localhost:44340/Identity/Account/Login?ReturnUrl=%2FIdentity%2FAccount%2FLogin%3FReturnUrl%3D%252FIdentity%252FAccount%252FLogin%253FReturnUrl%253D%25252FIdentity%25252FAccount%25252FLogin%25253F ReturnUrl%25253D%2525252FIdentity% 2525252F账户%2525252F登录%2525253FRet
HTTP 错误 404.15 - 未找到
请求过滤模块被配置为拒绝查询字符串太长的请求。
Program.cs
文件:
builder.Services.AddSingleton<IAuthorizationPolicyProvider, PermissionPolicyProvider>();
builder.Services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
builder.Services.Configure<SecurityStampValidatorOptions>(options =>
{
options.ValidationInterval = TimeSpan.Zero;
});
using Microsoft.AspNetCore.Authorization;
namespace UserManagement.Filters
{
public class PermissionRequirement : IAuthorizationRequirement
{
public string Permission { get; private set; }
public PermissionRequirement(string permission)
{
Permission = permission;
}
}
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
namespace UserManagement.Filters
{
public class PermissionPolicyProvider : IAuthorizationPolicyProvider
{
public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }
public PermissionPolicyProvider(IOptions<AuthorizationOptions> options)
{
FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
}
public Task<AuthorizationPolicy> GetDefaultPolicyAsync()
{
return FallbackPolicyProvider.GetDefaultPolicyAsync();
}
public Task<AuthorizationPolicy> GetFallbackPolicyAsync()
{
return FallbackPolicyProvider.GetDefaultPolicyAsync();
}
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
if (policyName.StartsWith("Permission", StringComparison.OrdinalIgnoreCase))
{
var policy = new AuthorizationPolicyBuilder();
policy.AddRequirements(new PermissionRequirement(policyName));
return Task.FromResult(policy.Build());
}
return FallbackPolicyProvider.GetPolicyAsync(policyName);
}
}
}
using Microsoft.AspNetCore.Authorization;
using System.Linq;
using System.Threading.Tasks;
namespace UserManagement.Filters
{
public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
{
public PermissionAuthorizationHandler()
{
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
if (context.User == null)
return;
var canAccess = context.User.Claims.Any(c => c.Type == "Permission" && c.Value == requirement.Permission && c.Issuer == "LOCAL AUTHORITY");
if (canAccess)
{
context.Succeed(requirement);
return;
}
}
}
}
登录方法
public async Task OnGetAsync(string returnUrl = null)
{
if (!string.IsNullOrEmpty(ErrorMessage))
{
ModelState.AddModelError(string.Empty, ErrorMessage);
}
returnUrl ??= Url.Content("~/");
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
ReturnUrl = returnUrl;
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
var username = new EmailAddressAttribute().IsValid(Input.Email) ? new MailAddress(Input.Email).User : Input.Email;
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(username, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
https://localhost:44340/Identity/Account/Login?ReturnUrl=%2FIdentity%2FAccount%2FLogin%3FReturnUrl%3D%252FIdentity%252FAccount%252FLogin%253FReturnUrl%253D%25252FIdentity%25252FAccount%25252FLogin%25253F ReturnUrl%25253D%2525252FIdentity% 2525252F账户%2525252F登录%2525253FRet
对于这个url,似乎
Identity/Account/Login
操作也需要登录,这会导致无限重定向循环。在此 PageModel 上添加 AllowAnonymousAttribute
。
[Microsoft.AspNetCore.Authorization.AllowAnonymous]
public class LoginModel : PageModel
如果添加属性但仍然出现此类错误,请务必通过启用匿名身份验证并禁用 Windows 身份验证来修改 IIS 配置。
另请检查您的
web.config
文件没有任何与 IIS 设置冲突的配置。 :
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="true" />
<windowsAuthentication enabled="false" />
</authentication>
</security>
</system.webServer>