我有一个 blazor 应用程序,想为其创建一个登录过程。因此我知道我可以搭建并删除默认的 MVC 页面来实现这一目标。
另一方面,我曾经读到,通过使用登录过程的控制器也应该可以实现相同的目的:
我的控制器:
using BlazorTestAuthorisierung.Data;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace BlazorTestAuthorisierung.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class LoginController : ControllerBase
{
private readonly SignInManager<Benutzer> _SignInManager;
[HttpPost]
public IActionResult Login([FromBody] Benutzer Benutzer)
{
var result = _SignInManager.PasswordSignInAsync(Benutzer.Email, Benutzer.EingegebenesPasswort, false, lockoutOnFailure: false).Result;
if (result.Succeeded)
{
IActionResult response = Ok(new { result = "" });
return response;
}
else
{
IActionResult response = Unauthorized(new { result=""});
return response;
}
}
public LoginController(SignInManager<Benutzer> signInManager)
{
_SignInManager = signInManager;
}
}
}
还有我的 blazor 登录信息
<EditForm Model=@LoginBenutzer OnValidSubmit="@OnLoginClick">
<InputText @bind-Value="LoginBenutzer.Email" />
<InputText @bind-Value="LoginBenutzer.EingegebenesPasswort" />
<button type="submit">
Anmelden
</button>
</EditForm>
<AuthorizeView Roles=Administrator>
<Authorized>
Admin
</Authorized>
</AuthorizeView>
@code{
private Benutzer LoginBenutzer = new Benutzer() {
Email = "",
EingegebenesPasswort = ""
};
private async Task OnLoginClick()
{
var serialized = JsonConvert.SerializeObject(LoginBenutzer);
var stringContent = new StringContent(serialized, Encoding.UTF8, "application/json");
var result = await http.PostAsync($"{navigationManager.BaseUri}api/Login", stringContent).ConfigureAwait(false);
}
}
登录结果显示登录成功。然而,当我返回 Blazor 应用程序时,它仍然无法识别用户已登录,因为它始终显示“未登录”。
<AuthorizeView>
<Authorized>
Logged in
</Authorized>
<NotAuthorized>
Not logged in
</NotAuthorized>
</AuthorizeView>
我认为授权后控制器的状态不会回到blazor圈。
任何有关如何实现我的目标或根本不可能实现的目标的帮助,将不胜感激。
我也尝试过,并遇到了与您相同的问题。然后我恍然大悟。当您使用 PostAsync 方法通过 WebClient 调用控制器时,它确实会在您的控制器中登录用户,但是该登录发生在与当前用户会话不同的会话中,因此您不会获取存储的会话的 cookie,因此就服务器而言,您的会话尚未登录。答案是使用您的表单来完成“action”标签的工作。所以你的控制器需要你已经建立的路由。您只需修改您的元素,如下所示
<EditForm Model=@LoginBenutzer action="api/Login" method="post">
<InputText @bind-Value="LoginBenutzer.Email" name="username" />
<InputText @bind-Value="LoginBenutzer.EingegebenesPasswort" name="password" />
<input type="hidden" value="@("~/" + navManager.Uri.Replace(navManager.BaseUri, String.Empty)) name="returnUrl" />
<button type="submit">
Anmelden
</button>
</EditForm>
因此,“action”标签告诉表单要发布到哪里,“method”标签告诉表单它是一个发布表单。您还会发现需要在输入中添加“名称”标签,当您编辑控制器方法时您会明白原因。我还添加了一个隐藏输入来保存返回 URL,因此登录时只会刷新您当时所在的任何页面。您必须修改控制器方法才能进行重定向,您将在下面看到这一点。因此,以这种方式修改控制器中的登录方法
[HttpPost]
public async Task<IActionResult> Login([FromForm] string name, [FromForm]
string password, [FromForm] string returnUrl)
{
await _signInManager.PasswordSignInAsync(name, password, false, false);
return Redirect(returnUrl ?? "/");
}
所以你看到你的方法参数是 [FromForm] 而不是 [FromBody]。您的参数名称需要与表单中的“名称”标签相对应。这是准系统,您实际上需要处理无效登录等等。但这是我能想到的最好的方法。
此外,您会发现这会导致页面刷新,因此如果您想在刷新过程中保留任何变量,请注入 ProtectedSessionStorage 并使用 SetAsync() 和 GetAsync() 来获取数据并将数据设置到会话数据存储中