【问题标题】:AuthorizeRouteView Authorizing and NotAuthorized parameters settingsAuthorizeRouteView Authorizing 和 NotAuthorized 参数设置
【发布时间】:2020-03-18 14:29:19
【问题描述】:

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

但是,它需要一个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");
            });
        }
    }

【问题讨论】:

  • 在 OnInitialised() 中尝试使用 NavigationManager 时总是报错,所以只能在 OnAfterRender 中使用。顺便说一句,我正在使用.Net Core 3.0,即使这样,它也永远不会进入任何可能的 2 个授权标签,我检查了我的 if(true) { } 语句。否则,即使没有被识别,它也会直接认为用户已获得授权,或者它甚至不关心这些标签。
  • 您尝试升级到 3.1-preview3 吗?
  • 您的主布局中有&lt;AuthorizedView&gt;AuthorizeAttribute 吗?
  • 你需要这个:NavigationManager.NavigateTo("Identity/Account/Login", forceLoad:true);看我的回答。
  • @aguafrommars 不,但这有什么改变吗?不应该通过检查用户是否被授权在路由之前触发重定向吗?而且我现在不会升级到预览版,除非非常必要,因为该应用程序应该在市场上。 (抱歉回复晚了,周末没在电脑上)

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


【解决方案1】:

RenderFragment&lt;AuthentificationState&gt; 是要渲染的一段 html。 您应该创建一个重定向到登录的组件:

RedectToLogin.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>

【讨论】:

  • 不行,已经试过了。它永远不会进入任何授权标签。而且您不能在OnInitialized 中使用NavigationManager,它会引发错误。你应该把它放在OnAfterRender
  • 如果您只是在NotAuthorized 中写一条消息怎么办?什么都不显示?
  • 我已经没有这个项目了,但我试过了,我记得什么也没看到。我还通过放置 if(true) { } 语句并在其中放置断点进行了检查,但从未到达。我发现有效的唯一方法是在每个页面和组件中使用&lt;AuthorizeView&gt;,但由于它始终是相同的模式,所以有点乏味。
  • 看起来很奇怪,这意味着你授权一切。我使用策略并且效果很好。可以浏览代码here
  • 我使用了包含在应用程序中的模板,并编写了与您完全相同的代码。我现在在另一台电脑上再试一次,然后告诉你结果。
【解决方案2】:

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

Mainlayout.Razor,我必须在顶部插入一个 using 以便可以使用重定向组件:

@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>

【讨论】:

  • 是的,我最终将&lt;RedirectToLogin&gt; 放入MainLayout.razor 而不是App.razor。这是它工作的唯一方法。如果您在我之前详细说明了您的答案(现在没有太多时间去做),我很乐意投票并将其标记为答案。
  • 我在这里相对较新,所以不确定您所说的“详细说明您的答案”是什么意思,但我在上面的答案中发布了更多详细信息。希望对您有所帮助。
【解决方案3】:

我遇到了一个类似的问题,我在 app.razor 中的 &lt;NotAuthorized&gt; 部分没有为未经授权的用户显示。在拔掉头发 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] 属性包含在 [Authorize] 属性中 部分。
  • 正在进行异步身份验证。

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

【讨论】:

    【解决方案4】:

    感谢 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

    【讨论】:

      【解决方案5】:

      事实上,您根本不需要定义额外的 RedirectToLogin 组件。您可以在 Login 组件的 OnInitialized 中完全实现这一点。是不是看起来更优雅?

      App.Razor:

      <Router AppAssembly="@typeof(App).Assembly">
          <Found Context="routeData">
              <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                  <NotAuthorized>
                      <Login />
                  </NotAuthorized>
              </AuthorizeRouteView>
          </Found>
          <NotFound>
              <PageTitle>Not found</PageTitle>
              <LayoutView Layout="@typeof(MainLayout)">
                  <p role="alert">Sorry, there's nothing at this address.</p>
              </LayoutView>
          </NotFound>
      </Router>
      

      登录组件:

      @page "/login"
      @layout NullLayout
      @inject NavigationManager nav
      <h3>Login</h3>
      
      @code {
          protected override void OnInitialized()
          {
              base.OnInitialized();
              if (nav.Uri != $"{nav.BaseUri}login")
              {
                  nav.NavigateTo("/login");
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-20
        • 1970-01-01
        • 2013-12-08
        • 2013-10-22
        • 2018-11-28
        • 2018-03-09
        • 2019-11-10
        相关资源
        最近更新 更多