我有一个使用身份的 ASP .NET Core 9 Razor Pages Web 应用程序。我从模板创建了它,附加了我的自定义 DbContext 并搭建了一些身份页面(
Identity/Pages/Account/Login
就是其中之一)。登录表单是标准的 - 它包含一个 <form>
和多个 <input>
(通过 InputModel
连接到 asp-for
的字段)和一个 <button type="submit">
。
在
Login.cshtml.cs
文件中,我通过 SignInManager<MyUserType>
执行登录(我省略了所有检查以简化示例代码):
[BindProperty]
public InputModel Input { get; set; }
...
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(Input.UserName, Input.Password, Input.RememberMe);
if (result.Succeeded)
{
return LocalRedirect(returnUrl);
}
else
{
ModelState.AddModelError(string.Empty, _localizer["LoginError"].Value);
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
现在我想添加 Web API 以便能够拥有其他消费者(iOS/Android 应用程序、PHP/Go 客户端等)。使用最少的 API 语法,我已经实现了
Login
(简化):
app.MapPost("/api/LoginUser", async (InputModel input, SignInManager<MyUserType> signInManager) =>
{
var result = await signInManager.PasswordSignInAsync(input.UserName, input.Password, input.RememberMe);
if (result.Succeeded)
{
return Results.Ok();
}
return Results.BadRequest($"SignInResult: {result}");
});
现在在发布登录表单时,我通过
HttpClient
执行 API 调用,如下所示:
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
if (ModelState.IsValid)
{
using (var client = new HttpClient())
{
var response = await client.PostAsJsonAsync($"{Request.Scheme}://{Request.Host}{Request.PathBase}/api/LoginUser", Input);
switch (response.StatusCode)
{
case System.Net.HttpStatusCode.OK:
//why user is not authenticated here and I need to perform another sign in?
if (!User.Identity.IsAuthenticated)
await _signInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberMe);
return Redirect(returnUrl);
break;
case System.Net.HttpStatusCode.BadRequest:
var errorText = response.Content.ReadAsStringAsync().Result;
ModelState.AddModelError(string.Empty, errorText);
return Page();
break;
}
}
// If we got this far, something failed, redisplay form
return Page();
}
这里的问题是,从 PageModel 的角度来看,用户仍未经过身份验证,我需要执行另一次登录。我觉得这是不正确的方式,但我不知道如何修复它。
那么如何通过 Web API 从 Razor 页面正确登录呢?附:我可以发布我的
Program.cs
,但我真的不知道是否需要它。
在 Razor 页面中,
User.Identity
是通过视图上下文分配的,视图上下文是在您最初访问页面时创建的。
我认为您正在尝试访问
User.Identity
对象,该对象 尚未更新,因为您没有刷新页面。
由于您的 API 操作已返回成功,您可以假设用户已登录,因此只需执行重定向即可。
switch (response.StatusCode)
{
case System.Net.HttpStatusCode.OK:
return Redirect(returnUrl);
break;
...
}