【问题标题】:How do I access the AuthorizationProvider outside of .razor files?如何访问 .razor 文件之外的 AuthorizationProvider?
【发布时间】:2021-06-19 02:25:18
【问题描述】:

我有一个带有剃须刀组件的 apsnet 核心应用程序。我使用 Discord OAuth 登录,并且可以读取 .razor 文件中的声明。

@foreach (var c in context.User.Claims)
        {
            <li>@c.Type: @c.Value</li>
        }

如何在剃须刀组件之外访问这些声明? 我想在我自己的数据库中查找 ID 与登录中的不和谐 ID 匹配的用户。

我发现我可以创建一个组件类,剃须刀组件可以从中继承,并且 AuthenticationStateProvider 包含用户/声明。但是我如何获得它或者我需要别的东西吗?

TestComponent.cs:

public class TestComponent: ComponentBase
{
    public string SomeTestText { get; set; }
    private AuthenticationStateProvider asp{ get; set; }
    
    public TestComponent()
    {

        SomeTestText = "Hello World!";
        GetUser();
    }

    private async Task GetUser()
    {
        var authState = await asp.GetAuthenticationStateAsync(); // asp is null
        var user = authState.User;
        SomeTestText = user.Claims.First().Value;
    }
}

Test.razor:

@page "/test"
@inherits Models.TestComponent;

<h1>@SomeTestText</h1>

编辑

仅添加 [Inject] 对我不起作用;它仍然为空。

由于它是 ComponentBase 而不是 PageModel(?) 我无法在构造函数中注入 ClaimsPrincipal。我也用 [Inject] 对其进行了测试,但它也不起作用。

这是我的 Startup.cs 以获得更多上下文:

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SlpyGrdn.Database;
using SlpyWeb.OAuth.Discord;
using System;
using System.Security.Claims;


namespace SlpyWeb
{
    public class Startup
    {
        public IConfiguration Configuration { get; }

        public Startup( IConfiguration configuration )
        {
            Configuration = new ConfigurationBuilder()
                .AddConfiguration(configuration)
                .AddEnvironmentVariables()
                .Build();

        }


        // 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.AddRazorPages();
            services.AddServerSideBlazor();

            services.AddAuthentication(opt =>
            {
                opt.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                opt.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                opt.DefaultChallengeScheme = DiscordEndPoints.AuthenticationScheme;
            })
            .AddCookie()
            .AddDiscord(x =>
            {   
                x.AppId = Environment.GetEnvironmentVariable("DISCORD_APP_ID");
                x.AppSecret = Environment.GetEnvironmentVariable("DISCORD_APP_SECRET");
                x.SaveTokens = true;
            });
            services.AddDbContext<SlpyDbContext>(options => options.UseNpgsql(Environment.GetEnvironmentVariable("CONNECTION_STRING")));


            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddScoped(svc => svc.GetService<IHttpContextAccessor>()?.HttpContext?.User ?? new ClaimsPrincipal());
        }

        // 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();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // app.UseDeveloperExceptionPage();
                // 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.UseForwardedHeaders(new ForwardedHeadersOptions
            {
                ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedProto
            });
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

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

编辑 2

我找到了解决方法:

@page "/test"

@inherits Models.TestComponent;

<h3>Test</h3>

<p>@SomeTestText</p>

@code { 


   [CascadingParameter] private AuthenticationStateProvider asp { get; set; }

   protected override async Task OnInitializedAsync()
   {

       var authState = await asp.GetAuthenticationStateAsync();
       var user = authState.User;
       DoSomething(user);

       await base.OnInitializedAsync();
   }
}

“DoSomething”是TestComponent 中的一个方法。所以我只是将用户声明转发给我的班级。不是最好的解决方案,但它现在可以工作。

【问题讨论】:

标签: c# asp.net-core blazor


【解决方案1】:

您可以使用 [inject] 属性来@inject 向 DI 注册的类。

[Inject] private AuthenticationStateProvider asp {get; set;}

【讨论】:

  • 尝试将@attribute [Authorize] 添加到Test.razor 的顶部
【解决方案2】:

我不熟悉 Discord OAuth 实施。但是如果我遵循 razor 组件,中间件将只使用 HttpContext.User 对象来传递当前身份。因此,我不会使用特定的实现,而是依赖 .net 提供的支持类,并且只使用位于 HttpContext.User 的 ClaimsPrincipal

因此,在您开始访问用户之前,它需要在 DI 容器中注册,因为默认情况下不会这样做。

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped(svc => svc.GetService<IHttpContextAccessor>()?.HttpContext?.User ?? new ClaimsPrincipal());

然后你可以通过添加在任何组件中注入 ClaimsPrinciple

@inject ClaimsPrincipal User

如果这需要出现在每个 razor 组件/视图/页面中,您可以在 _ViewImports.cshtml 文件中添加 @inject 语句。此共享视图已添加到您所有的 razor vies 中。

现在,如果您需要在 razor 组件之外访问它,只需像这样将 ClaimsPrincipal 添加到您的构造函数中。

public class OutsideRazorComponent 
{
    private readonly ClaimsPrincipal _user;

    public OutsideRazorComponent(ClaimsPrincipal user)
    {
        _user = user;
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 1970-01-01
    • 2014-05-24
    相关资源
    最近更新 更多