C# SignInManager.SignInAsync不';不要让我登录(Vue.js SPA)
我在一个由dotnet core 2.1 API后端和Vue.js SPA前端组成的应用程序上遇到了一些奇怪的身份验证问题 我已经准备好了使用Auth API控制器在后端登录和注销的所有关键元素和层,并且在Vue应用程序上有了一个基本的登录页面,我可以用它登录 前端应用程序包括“登陆”时的3个关键页面(点击此处登录)、登录用户的“主页”和登录页面本身 如果我登录,那么登录API调用将返回我的基本用户数据和角色,因此我将其存储在Vuex状态并使用它加载主页。但是,如果我试图通过将页面刷新回根URL返回登录页面,那么Vue应用程序应触发一个例程,该例程将评估用户状态并相应地进行调整(它首先通过检查Vuex状态来执行此操作,如果为空,则调用auth controller获取用户和角色数据并重新填充自身),因此,当我登录时,我应该被重定向回登录的“主页”。这不会发生-相反,会显示“登录”(未登录)页面 我有一些普通的日志记录,随着我的离去,我又添加了一些。很明显,当我打第二个电话时,出于某种原因,我不再被授权,尽管我一辈子都不知道为什么 我曾经非常成功地使用过这个设置-唯一的区别是dev API后端是ASP.Net核心,而不是.Net Framework 我愿意知道从哪里开始考虑这个问题 这是我的启动配置C# SignInManager.SignInAsync不';不要让我登录(Vue.js SPA),c#,vue.js,asp.net-core,asp.net-core-webapi,C#,Vue.js,Asp.net Core,Asp.net Core Webapi,我在一个由dotnet core 2.1 API后端和Vue.js SPA前端组成的应用程序上遇到了一些奇怪的身份验证问题 我已经准备好了使用Auth API控制器在后端登录和注销的所有关键元素和层,并且在Vue应用程序上有了一个基本的登录页面,我可以用它登录 前端应用程序包括“登陆”时的3个关键页面(点击此处登录)、登录用户的“主页”和登录页面本身 如果我登录,那么登录API调用将返回我的基本用户数据和角色,因此我将其存储在Vuex状态并使用它加载主页。但是,如果我试图通过将页面刷新回根URL
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory,
ApplicationDbContext context, RoleManager<IdentityRole> roleManager, UserManager<ApplicationUser> userManager)
{
if (env.IsDevelopment())
{
app
.UseDeveloperExceptionPage()
.UseDatabaseErrorPage();
}
else
{
app
.UseExceptionHandler("/Home/Error")
.UseHsts();
}
app
.UseAuthentication()
.UseHttpsRedirection()
.UseStaticFiles()
.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "VueApp";
if (env.IsDevelopment())
{
spa.UseVueCliServer("serve");
}
});
DbInitializer.Initialize(context, roleManager, userManager, env, loggerFactory);
}
当我在登录后端但清除Vuex状态(通过刷新页面)后加载应用程序时,应用程序会尝试调用此方法
[Authorize]
[HttpGet]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<ActionResult<CurrentUserJsonModel>> Get()
{
if (HttpContextAccessor.HttpContext.User != null)
{
if (HttpContextAccessor.HttpContext.User.Identity.IsAuthenticated)
return new CurrentUserJsonModel
{
UserName = HttpContextAccessor.HttpContext.User.Identity.Name,
Roles = await authService.GetRolesAsync(HttpContextAccessor.HttpContext.User)
};
return Forbid();
}
return Unauthorized();
}
我在Visual Studio中的控制台输出如下所示
public async Task<ActionResult<CurrentUserJsonModel>> LogIn(LoginJsonModel model)
{
if (model == null) return BadRequest();
if (!ModelState.IsValid) return BadRequest(ModelState);
var result = await authService.LogInAsync(model.UserName, model.Password);
if (!result.Succeeded)
return BadRequest(result.Errors.Select(e => new ErrorJsonModel(e)).ToArray());
var principal = User;
return new CurrentUserJsonModel
{
UserName = result.UserName,
Roles = await authService.GetRolesAsync(model.UserName, model.Password)
};
}
public async Task<AuthResult> LogInAsync(ApplicationUser user)
{
if (user != null)
{
await identityService.SignOutAsync();
await identityService.SignInAsync(user);
}
return user != null
? new AuthResult(user)
: new AuthResult("Password or Email address incorrect.");
}
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:44368/api/auth
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "Auth"}. Executing action Ddm.Lcp.Iptn.Dashboard.Web.Api.AuthController.Get (Ddm.Lcp.Iptn.Dashboard.Web)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Ddm.Lcp.Iptn.Dashboard.Web.Api.AuthController.Get (Ddm.Lcp.Iptn.Dashboard.Web) in 10.8469ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 18.1495ms 401
这表明Cookie正在受到挑战,因为它们应该在我的设置下进行设置-它确实感觉到实际的登录创建没有实际工作
问题是。。。为什么会失败
更新:根据@Kirk的说法,这可能与cookie和Identity.Application之间的方案不匹配有关。我已经通过在Startup中注释出cookie元素进行了测试,在本例中,我发现自己处于一个递归循环中——我将cookie元素添加到Startup.cs以使我能够从授权结果中获得合理的响应
我需要能够做到这一点,但不要重定向到(在我的应用程序中)不存在且不存在的登录页面,因为它是SPA。
signInManager。SignInAsync(…)
使用标识。应用程序
方案,而不是您都注册并配置为默认的Cookies
方案。要使用标识并自定义它使用的cookie,请使用
替换以下内容:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options =>
{
options.SlidingExpiration = true;
options.Events.OnRedirectToLogin = cxt =>
{
cxt.Response.StatusCode = 401;
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = cxt =>
{
cxt.Response.StatusCode = 403;
return Task.CompletedTask;
};
options.Events.OnRedirectToLogout = cxt => Task.CompletedTask;
});
-与-:
services.ConfigureApplicationCookie(options =>
{
options.SlidingExpiration = true;
options.Events.OnRedirectToLogin = cxt =>
{
cxt.Response.StatusCode = 401;
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = cxt =>
{
cxt.Response.StatusCode = 403;
return Task.CompletedTask;
};
options.Events.OnRedirectToLogout = cxt => Task.CompletedTask;
});
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:44368/api/auth
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "Auth"}. Executing action Ddm.Lcp.Iptn.Dashboard.Web.Api.AuthController.Get (Ddm.Lcp.Iptn.Dashboard.Web)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Ddm.Lcp.Iptn.Dashboard.Web.Api.AuthController.Get (Ddm.Lcp.Iptn.Dashboard.Web) in 10.8469ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 18.1495ms 401
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options =>
{
options.SlidingExpiration = true;
options.Events.OnRedirectToLogin = cxt =>
{
cxt.Response.StatusCode = 401;
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = cxt =>
{
cxt.Response.StatusCode = 403;
return Task.CompletedTask;
};
options.Events.OnRedirectToLogout = cxt => Task.CompletedTask;
});
services.ConfigureApplicationCookie(options =>
{
options.SlidingExpiration = true;
options.Events.OnRedirectToLogin = cxt =>
{
cxt.Response.StatusCode = 401;
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = cxt =>
{
cxt.Response.StatusCode = 403;
return Task.CompletedTask;
};
options.Events.OnRedirectToLogout = cxt => Task.CompletedTask;
});