我需要 blazor 服务器应用程序中的登录页面的简单示例,而无需查看或访问(在 url 字符串中)任何其他元素

问题描述 投票:0回答:2

我会缩短我的问题。 xD

所以,我使用VS2022,C#。

  1. 使用现有 VS 2022 模板创建带有个人帐户的 blazorserverapp - 好的。

  2. 使用 EF 将数据库迁移到我的 postgres 数据库 - 完成。

  3. 登录创建的网站 - 确定。

  4. 登录/注销工作正常。

问题:

  1. 如何避免在未登录时看到创建的 blazorserver 应用程序网页上的所有元素?

  2. 如何避免在未登录时通过输入网址来访问网页元素,例如: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; }

}

也许它可以帮助有类似问题的人。 这样案件就可以结案了。

asp.net-core authentication asp.net-identity blazor-server-side asp.net-authorization
2个回答
1
投票

我在 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>

0
投票

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 还是我遗漏了什么?

© www.soinside.com 2019 - 2024. All rights reserved.