我会缩短我的问题。 xD
所以,我使用VS2022,C#。
使用现有 VS 2022 模板创建带有个人帐户的 blazorserverapp - 好的。
使用 EF 将数据库迁移到我的 postgres 数据库 - 完成。
登录创建的网站 - 确定。
登录/注销工作正常。
问题:
如何避免在未登录时看到创建的 blazorserver 应用程序网页上的所有元素?
如何避免在未登录时通过输入网址来访问网页元素,例如:https://localhost:7164/counter?
必须在代码中更改哪些内容才能禁止显示/访问(未登录时)?
一个没有任何元素的简单空(白色)页面,除了一个带有用户/密码字段 a 的小窗口以及空登录页面内部和中间的一个按钮,那就太好了。
但是类似的东西,实际上很简单,在任何地方都找不到——我在谷歌上找了好几个星期……
每个人都在展示/呈现 blazorserver 登录(个人帐户、SQL Server 身份验证或 - 对我来说理想的 - PostgreSQL)示例,但是:您可以在未登录时查看/访问所有元素。
有人可以提供例子吗?
谢谢 最好
P.S.:抱歉我的英语不好(我来自奥地利)
这是我的 MainLayout.razor:
@inherits LayoutComponentBase
<PageTitle>msgsolutions</PageTitle>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4 auth">
<LoginDisplay />
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
这是我的 Index.razor:
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
这是共享/LoginDisplay.razor:
<AuthorizeView>
<Authorized>
<a href="Identity/Account/Manage">Hello, @context.User.Identity?.Name!</a>
<form method="post" action="Identity/Account/LogOut">
<button type="submit" class="nav-link btn btn-link">Log out</button>
</form>
</Authorized>
<NotAuthorized>
<a href="Identity/Account/Register">Register</a>
<a href="Identity/Account/Login">Log in</a>
</NotAuthorized>
这里是Areas/Identity/Pages/shared/_LoginPartial.cshtml:
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity?.Name!</a>
</li>
<li class="nav-item">
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="/" method="post">
<button type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
}
</ul>
如果能将其显示在登录页面的中间,那就太好了。 并且此登录页面必须首先出现,并且在用户登录之前不得在第一页上显示其他元素(示例):
<style>
#login .container #login-row #login-column #login-box {
margin-top: 120px;
max-width: 400px;
height: 280px;
border: 1px solid #9C9C9C;
background-color: #EAEAEA;
margin-left: auto;
margin-right: auto;
}
input[type=submit] {
background: #00BBFF;
}
#login .container #login-row #login-column #login-box #login-form {
padding: 20px;
}
#login .container #login-row #login-column #login-box #login-form #register-link {
margin-top: -85px;
}
</style>
<div id="login">
<h3 class="text-center text-white pt-5">Login form</h3>
<div class="container">
<div id="login-row" class="row justify-content-center align-items-center">
<div id="login-column" class="col-md-6">
<div id="login-box" class="col-md-12">
<form id="login-form" class="form" action="" method="post">
<h3 class="text-center text-info">Login</h3>
<EditForm Model=@login>
<div class="form-group">
<label for="Username" class="text-info">Username:</label><br>
<InputText @[email protected] type="text" name="username" id="username" class="form-control" />
</div>
<div class="form-group">
<label for="Password" class="text-info">Password:</label><br>
<InputText @[email protected] type="password" name="password" id="password" class="form-control" />
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary btn-outline-primary" value="Authenticate" @onclick="@(()=>IsLoginValid())"></input>
</div>
</EditForm>
</form>
</div>
</div>
</div>
</div>
</div>
编辑(已解决): 我们能够使用这种方式来管理它:使用 Index.razor (其中包含:“/”)并将内容替换为:
@page "/"
@inject NavigationManager NavigationManager
@inject IJSRuntime jsRuntime
@inject IHttpContextAccessor httpContext
@using System.Net;
<PageTitle>OurLogin</PageTitle>
<style>
#login .container #login-row #login-column #login-box {
margin-top: 120px;
max-width: 400px;
height: 280px;
border: 1px solid #9C9C9C;
background-color: #EAEAEA;
margin-left: auto;
margin-right: auto;
}
input[type=submit] {
background: #00BBFF;
}
#login .container #login-row #login-column #login-box #login-form {
padding: 20px;
}
#login .container #login-row #login-column #login-box #login-form #register-link {
margin-top: -85px;
}
</style>
<div id="login">
<h3 class="text-center text-white pt-5">Login form</h3>
<div class="container">
<div id="login-row" class="row justify-content-center align-items-center">
<div id="login-column" class="col-md-6">
<div id="login-box" class="col-md-12">
<form id="login-form" class="form" action="" method="post">
<h3 class="text-center text-info">Login</h3>
<EditForm Model=@login>
<div class="form-group">
<label for="Username" class="text-info">Username:</label><br>
<InputText @[email protected] type="text" name="username" id="username" class="form-control" />
</div>
<div class="form-group">
<label for="Password" class="text-info">Password:</label><br>
<InputText @[email protected] type="password" name="password" id="password" class="form-control" />
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary btn-outline-primary" value="Authenticate" @onclick="@(()=>IsLoginValid())"></input>
</div>
</EditForm>
</form>
</div>
</div>
</div>
</div>
</div>
<p>@login.successmsg</p>
@code
{
public async Task IsLoginValid()
{
string hashedpassword = await hashTask;
string status = await UserAuth(hashedpassword, login.user);
string successmsg = "";
if (status == "Authenticated!")
{
successmsg = "Authentication successful! Redirecting...";
Redirect();
}
else if (status == "Not Authenticated!")
{
successmsg = "Wrong customer ID, username or password! Please try again!";
}
else
{
successmsg = status;
}
Thread.Sleep(500);
login.successmsg = successmsg;
}
[CascadingParameter]
public ErrorHandler? ErrorHandler { get; set; }
}
也许它可以帮助有类似问题的人。 这样案件就可以结案了。
我在 Blazor Server 应用程序上有同样的要求,我用这种方式解决了它,我希望它能满足您的需求。我的灵感来自于 https://askianoor.medium.com/ Different-ways-of-authorization-in-blazor-redirect-to-login-blazor-46120d629387.
首先,为登录页面创建一个独特的布局,我们将其命名为“LoginLayout.razor”;示例:
<div class="container py-3">
<link href="css/login.css" rel="stylesheet">
@Body
<LoginError visible="false"/>
</div>
然后,创建一个登录页面,使用登录布局;我们称之为“Login.razor”:
@layout LoginLayout
@page "/login"
@attribute [AllowAnonymous]
<div class="text-center">
... your logo or whatever
<EditForm class="form-signin mb-4" Model="@_credential" OnSubmit="@Authenticate">
<div class="form-group">
<label for="user-name">User name</label>
<InputText class="form-control" id="user-name" aria-describedby="emailHelp" placeholder="Indirizzo e-mail" @bind-Value=@_credential.UserName />
</div>
<div class="form-group">
<label for="password">Password</label>
<InputText type="password" class="form-control" id="password" placeholder="Password" @bind-Value=@_credential.Password />
</div>
<div class="form-group">
<button type="submit" id="login" name="login" class="btn btn-primary">Login</button>
</div>
... other stuff, like "forgot my password", etc...
</EditForm>
</div>
@code {
public class Credential { public string UserName { get; set; } = ""; public string Password { get; set; } = ""; }
private Credential _credential = new Credential();
private void Authenticate()
{
.... perform authentication using _credential fields
}
}
然后,准备一个用于重定向到登录页面的组件,我们称之为“RedirectToLogin.razor”:
@inject NavigationManager NavigationManager
@code {
[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; } = null;
protected override async Task OnInitializedAsync()
{
var authState = await AuthState!;
if (authState?.User?.Identity == null || !authState.User.Identity.IsAuthenticated)
{
var returnUrl = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
if (string.IsNullOrEmpty(returnUrl))
NavigationManager.NavigateTo("/login", true);
else
NavigationManager.NavigateTo("/login?returnUrl=" + returnUrl, true);
}
}
}
最后,最重要的是,修改您的 App.razor,以便执行到登录页面的重定向,以防用户未经过身份验证:
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" >
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
<Authorizing>
<p>Logging in...</p>
</Authorizing>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
Giorgio Barchiesi 的接受答案在我看来似乎有道理,但最终效果不佳。 AuthorizedRouteView 组件似乎存在错误。为了让它工作,我必须将 RedirectToLogin 指令移至 MainLayout.razor,如下所示:
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
</div>
<article class="content px-4">
<AuthorizeView>
<Authorized>
@Body
</Authorized>
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
<Authorizing>
<em>Authorizing...</em>
</Authorizing>
</AuthorizeView>
</article>
</main>
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
我再次认为问题出在 AuthorizedRouteView 还是我遗漏了什么?