添加身份验证时出现无限循环
Getting infinite loop when adding Authentication
我有认证用户的认证 API (jwt)。将其用于多个客户,现在正在添加第二个客户。第一个可以正常工作。
我确定问题出在这部分:
var _authorizePolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
var _serviceProvider = builder.Services.BuildServiceProvider();
var _authenticationSettings = _serviceProvider.GetService<IAuthenticationSettings>();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddCookie(JwtBearerDefaults.AuthenticationScheme,
options => {
options.LoginPath = _authenticationSettings.LoginPath;
options.AccessDeniedPath = _authenticationSettings.AccessDeniedPath;
options.Events = new CookieAuthenticationEvents
{
// Check if JWT needs refreshment
OnValidatePrincipal = RefreshTokenMonitor.ValidateAsync
};
options.Cookie.Name = "MainAppCookie";
}
);
builder.Services.AddMvc(config =>
{
config.Filters.Add(new AuthorizeFilter(_authorizePolicy));
})
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
})
.AddViewOptions(options => options.HtmlHelperOptions.ClientValidationEnabled = true);
我有相同的代码(Cookie 的不同名称)是第一个应用程序,在那里工作正常。
这里有 AccountController:
public class AccountController : Controller
{
私人只读 ISecurityManager _securityManager;
public AccountController(ISecurityManager securityManager)
{
_securityManager = securityManager;
}
public async Task<IActionResult> Login()
{
return View(new LoginViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([FromForm] LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (!ModelState.IsValid)
{
ViewBag.ErrorMessage = "Input data incorrect. Please try again";
ModelState.AddModelError(string.Empty, "Invalid login form");
return View(model);
}
if (await _securityManager.LoginUser(model.Email, model.Password))
return RedirectToLocal(returnUrl);
else
{
ViewBag.ErrorMessage = "Invalid login attempt.";
return View(model);
}
return View(model);
}
public async Task<IActionResult> AccessDenied()
{
return View();
}
[HttpGet]
[Route("account/password/forgot")]
public async Task<IActionResult> ForgotPassword()
{
return View(new ForgotPasswordModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPasswordSubmit(ForgotPasswordModel model)
{
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
[Route("account/password/confirmation")]
public async Task<IActionResult> ForgotPasswordConfirmation()
{
return View();
}
[HttpGet]
[Route("account/password/reset")]
public async Task<IActionResult> ResetPassword()
{
return View(new PasswordResetModel());
}
[HttpPost]
public async Task<IActionResult> ResetPasswordSubmit(PasswordResetModel model)
{
return RedirectToAction(nameof(Login), new { });
}
public async Task<IActionResult> LogOut()
{
//await _securityManager.LogOut();
return RedirectToAction(nameof(Login));
}
// Prevent session stealing
private IActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
return Redirect(returnUrl);
else
return RedirectToAction(nameof(HomeController.Index), "Home");
}
}
这里是您的实际登录名:
private async Task<bool> Login(AuthResult token)
{
if(token.Token.IsNullOrEmpty())
return false;
await LogOut();
var _tokenHandler = new JwtSecurityTokenHandler();
var _tokenSettings = _jwtTokenValidationSettings.CreateTokenValidationParameters();
var _principal = _tokenHandler.ValidateToken(token.Token, _tokenSettings, out var _validatedToken);
var _identity = _principal.Identity as ClaimsIdentity;
var _securityToken = _tokenHandler.ReadToken(token.Token) as JwtSecurityToken;
var _extraClaims = _securityToken.Claims.Where(c => !_identity.Claims.Any(x => x.Type == c.Type)).ToList();
_extraClaims.Add(new Claim("jwt", token.Token));
_extraClaims.Add(new Claim("refreshToken", token.RefreshToken));
_identity.AddClaims(_extraClaims);
var _authenticationProperties = new AuthenticationProperties()
{
IssuedUtc = _identity.Claims.First(c => c.Type == JwtRegisteredClaimNames.Iat)?.Value.ToInt64().ToUnixEpochDate(),
ExpiresUtc = _identity.Claims.First(c => c.Type == JwtRegisteredClaimNames.Exp)?.Value.ToInt64().ToUnixEpochDate(),
IsPersistent = true
};
await _httpContext.SignInAsync(JwtBearerDefaults.AuthenticationScheme, _principal, _authenticationProperties);
return _identity.IsAuthenticated;
}
并进一步澄清...这是我得到的错误:
您的 LoginControler
(或其多个操作)需要 [AllowAnonymous]
才能绕过身份验证检查。否则,用户将无权查看这些路线。
错误实际上是在 AccountController 的 [AllowAnonymous] 属性中。
删除它并构建项目,再次添加属性。很有魅力:)
我有认证用户的认证 API (jwt)。将其用于多个客户,现在正在添加第二个客户。第一个可以正常工作。 我确定问题出在这部分:
var _authorizePolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
var _serviceProvider = builder.Services.BuildServiceProvider();
var _authenticationSettings = _serviceProvider.GetService<IAuthenticationSettings>();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddCookie(JwtBearerDefaults.AuthenticationScheme,
options => {
options.LoginPath = _authenticationSettings.LoginPath;
options.AccessDeniedPath = _authenticationSettings.AccessDeniedPath;
options.Events = new CookieAuthenticationEvents
{
// Check if JWT needs refreshment
OnValidatePrincipal = RefreshTokenMonitor.ValidateAsync
};
options.Cookie.Name = "MainAppCookie";
}
);
builder.Services.AddMvc(config =>
{
config.Filters.Add(new AuthorizeFilter(_authorizePolicy));
})
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
})
.AddViewOptions(options => options.HtmlHelperOptions.ClientValidationEnabled = true);
我有相同的代码(Cookie 的不同名称)是第一个应用程序,在那里工作正常。
这里有 AccountController:
public class AccountController : Controller
{ 私人只读 ISecurityManager _securityManager;
public AccountController(ISecurityManager securityManager)
{
_securityManager = securityManager;
}
public async Task<IActionResult> Login()
{
return View(new LoginViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([FromForm] LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (!ModelState.IsValid)
{
ViewBag.ErrorMessage = "Input data incorrect. Please try again";
ModelState.AddModelError(string.Empty, "Invalid login form");
return View(model);
}
if (await _securityManager.LoginUser(model.Email, model.Password))
return RedirectToLocal(returnUrl);
else
{
ViewBag.ErrorMessage = "Invalid login attempt.";
return View(model);
}
return View(model);
}
public async Task<IActionResult> AccessDenied()
{
return View();
}
[HttpGet]
[Route("account/password/forgot")]
public async Task<IActionResult> ForgotPassword()
{
return View(new ForgotPasswordModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPasswordSubmit(ForgotPasswordModel model)
{
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
[Route("account/password/confirmation")]
public async Task<IActionResult> ForgotPasswordConfirmation()
{
return View();
}
[HttpGet]
[Route("account/password/reset")]
public async Task<IActionResult> ResetPassword()
{
return View(new PasswordResetModel());
}
[HttpPost]
public async Task<IActionResult> ResetPasswordSubmit(PasswordResetModel model)
{
return RedirectToAction(nameof(Login), new { });
}
public async Task<IActionResult> LogOut()
{
//await _securityManager.LogOut();
return RedirectToAction(nameof(Login));
}
// Prevent session stealing
private IActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
return Redirect(returnUrl);
else
return RedirectToAction(nameof(HomeController.Index), "Home");
}
}
这里是您的实际登录名:
private async Task<bool> Login(AuthResult token)
{
if(token.Token.IsNullOrEmpty())
return false;
await LogOut();
var _tokenHandler = new JwtSecurityTokenHandler();
var _tokenSettings = _jwtTokenValidationSettings.CreateTokenValidationParameters();
var _principal = _tokenHandler.ValidateToken(token.Token, _tokenSettings, out var _validatedToken);
var _identity = _principal.Identity as ClaimsIdentity;
var _securityToken = _tokenHandler.ReadToken(token.Token) as JwtSecurityToken;
var _extraClaims = _securityToken.Claims.Where(c => !_identity.Claims.Any(x => x.Type == c.Type)).ToList();
_extraClaims.Add(new Claim("jwt", token.Token));
_extraClaims.Add(new Claim("refreshToken", token.RefreshToken));
_identity.AddClaims(_extraClaims);
var _authenticationProperties = new AuthenticationProperties()
{
IssuedUtc = _identity.Claims.First(c => c.Type == JwtRegisteredClaimNames.Iat)?.Value.ToInt64().ToUnixEpochDate(),
ExpiresUtc = _identity.Claims.First(c => c.Type == JwtRegisteredClaimNames.Exp)?.Value.ToInt64().ToUnixEpochDate(),
IsPersistent = true
};
await _httpContext.SignInAsync(JwtBearerDefaults.AuthenticationScheme, _principal, _authenticationProperties);
return _identity.IsAuthenticated;
}
并进一步澄清...这是我得到的错误:
您的 LoginControler
(或其多个操作)需要 [AllowAnonymous]
才能绕过身份验证检查。否则,用户将无权查看这些路线。
错误实际上是在 AccountController 的 [AllowAnonymous] 属性中。 删除它并构建项目,再次添加属性。很有魅力:)