AuthorizeRouteView授权和未授权参数设置

时间:2019-11-22 13:45:00

标签: c# asp.net blazor blazor-server-side

每当非登录用户尝试访问页面时,我都想使用NotAuthorized标签中的<AuthorizeRouteView>属性重定向到登录页面。

Howewer,它需要一个RenderFragment<AuthentificationState>类型的参数。我应该怎样设置此参数以呈现登录页面?

编辑:代码非常简单。我使用身份存储在应用程序中的Blazor服务器端项目模板,只是像这样添加了RedirectToLogin.razor

@inject NavigationManager NavigationManager
@code { 
    protected override void OnAfterRender()
    {
        NavigationManager.NavigateTo("counter"); //for an unknown reason, the "Identity/Account/Login" redirect doesn't work.
    }
}

并修改了App.razor

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    @if(true) { } //Used for breakpoint.
                    <RedirectToLogin />
                </NotAuthorized>
                <Authorizing>
                    @if(true) { } //Used for breakpoint.
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

我没有碰过Startup.cs,所以看起来像这样:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDefaultIdentity<IdentityUser>()
                .AddEntityFrameworkStores<ApplicationDbContext>();
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
            services.AddSingleton<WeatherForecastService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }

4 个答案:

答案 0 :(得分:3)

我遇到了类似的问题,我在 app.razor 中的 <NotAuthorized> 部分没有为未经授权的用户显示。在拔出我的头发 3 天后,我也在其他答案中提到的 MainLayout.razor 中寻求解决方案。一个干净的项目的最后一次尝试让我意识到我是一个多么糟糕的程序员,因为我终于找到了答案。

我没有完全阅读文档,我可以在其中找到问题的原因。在以下页面上:https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-5.0#customize-unauthorized-content-with-the-router-component 你会发现 NotAuthorized 部分是如何被调用的。我完全错过了第二个要点:

<块引用>

Router 组件,结合 AuthorizeRouteView 组件,在以下情况下允许应用指定自定义内容:

  • 未找到内容。
  • 用户未通过应用到组件的 [授权] 条件。 [Authorize] 属性包含在 [Authorize] 属性中 部分。
  • 正在进行异步身份验证。

这意味着 <NotAuthorized> 部分仅在路由端点具有 Authorize 标记时才被调用/显示。在我的情况下,路由将转到我的索引页面,没有 Authorize 标签....

答案 1 :(得分:1)

RenderFragment<AuthentificationState>是要呈现的一段html。 您应该创建一个重定向到登录名的组件:

ReditectToLogin.razor

@inject NavigationManager _navigationManager

@code {
    protected override Initialized()
    {
        _navigationManager.NavigateTo("login");
    }
}

App.razor

...
<AuthorizeRouteView>
...
    <NotAuthorized>
       <ReditectToLogin />
    </NotAuthorized>
</AuthorizeRouteView>

MainLayout.razor

<div class="sidebar bg-light">
    <NavMenu />
</div>

<div class="main bg-light mb-2">
...
    <div class="content px-4">
        <AuthorizeView>
            <Authorized>
                @Body
            </Authorized>
        </AuthorizeView>

答案 2 :(得分:0)

我已经使用了如上所述的RedirectToLogin组件,但是只有在进行以下更改后,我才能使它工作:

Mainlayout.Razor ,我必须在顶部插入一个use,以便可以使用Redirect Component:

@using MyBlazorApp.Pages
        <AuthorizeView>
            <Authorized>
                @* code omitted for brevity *@
            </Authorized>
            <NotAuthorized>
                <RedirectToLogin />
            </NotAuthorized>
        </AuthorizeView>

我必须在 RedirectToLogin

中执行以下操作
@inject NavigationManager nav
@code {
        protected override Task OnAfterRenderAsync(bool firstRender) {
            nav.NavigateTo("/login");
            return base.OnAfterRenderAsync(firstRender);
        }
    } 

...最后是 App.razor

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <CascadingAuthenticationState>
            <LayoutView Layout="@typeof(MainLayout)">

                <p>Sorry, there's nothing at this address</p>
            </LayoutView>
        </CascadingAuthenticationState>
    </NotFound>
</Router>

答案 3 :(得分:0)

感谢 MartinH,我没有花 3 天时间拔头发。

对于需要澄清“授权属性”的任何其他人,这里有一个示例...

VerifyAuth.razor

@page "/verifyauth"
@attribute [Authorize]    @*<--RIGHT HERE!!!*@

<div class="container">

    <h3 class="text-center">Verify Auth</h3>

</div>

@code {

}

App.razor

<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" >
            <Authorizing>
                <text>Please wait, we are authorizing you...</text>
            </Authorizing>
            <NotAuthorized>
                @if (context.User.Identity.IsAuthenticated == false)
                {
                    <RedirectToLogin />
                }
                else
                {
                    <p>You are not authorized to access this resource.</p>
                }
            </NotAuthorized>
        </AuthorizeRouteView>
    </Found>
    <NotFound>
        <CascadingAuthenticationState>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there is nothing at this address.</p>
            </LayoutView>
        </CascadingAuthenticationState>
    </NotFound>
</Router>

RedirectToLogin.razor

@inject NavigationManager NavManager

@code {
    protected override void OnInitialized()
    {
        NavManager.NavigateTo("/login");
    }
}

参考: https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-5.0#customize-unauthorized-content-with-the-router-component