C# 如何访问.razor文件之外的AuthorizationProvider?

C# 如何访问.razor文件之外的AuthorizationProvider?,c#,asp.net-core,blazor,C#,Asp.net Core,Blazor,我有一个带有razor组件的apsnet核心应用程序。我使用Discord OAuth进行登录,可以读取.razor文件中的声明 @foreach (var c in context.User.Claims) { <li>@c.Type: @c.Value</li> } Test.razor: @page "/test" @inherits Models.TestComponent; <

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

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

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

<h1>@SomeTestText</h1>
@page”/test
@继承Models.TestComponent;
@一些测试文本
编辑

仅仅添加[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");
            });
        }
    }
}
使用Microsoft.AspNetCore.Authentication.Cookies;
使用Microsoft.AspNetCore.Builder;
使用Microsoft.AspNetCore.Hosting;
使用Microsoft.AspNetCore.Http;
使用Microsoft.EntityFrameworkCore;
使用Microsoft.Extensions.Configuration;
使用Microsoft.Extensions.DependencyInjection;
使用Microsoft.Extensions.Hosting;
使用SlpyGrdn.Database;
使用SlpyWeb.OAuth.Discord;
使用制度;
使用System.Security.Claims;
名称空间SlpyWeb
{
公营创业
{
公共IConfiguration配置{get;}
公共启动(IConfiguration配置)
{
配置=新的ConfigurationBuilder()
.AddConfiguration(配置)
.AddenEnvironmentVariables()
.Build();
}
//此方法由运行时调用。请使用此方法将服务添加到容器中。
//有关如何配置应用程序的更多信息,请访问https://go.microsoft.com/fwlink/?LinkID=398940
public void配置服务(IServiceCollection服务)
{
services.AddRazorPages();
AddServerSideBlazor();
services.AddAuthentication(opt=>
{
opt.DefaultScheme=CookieAuthenticationDefaults.AuthenticationScheme;
opt.defaultsignnscheme=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(options=>options.UseNpgsql(Environment.GetEnvironmentVariable(“CONNECTION_STRING”));
services.AddSingleton();
services.AddScoped(svc=>svc.GetService()?.HttpContext?.User??newclaimsprincipal());
}
//此方法由运行时调用。请使用此方法配置HTTP请求管道。
public void配置(IApplicationBuilder应用程序、IWebHostEnvironment环境)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
其他的
{
app.UseExceptionHandler(“/Error”);
//app.UseDeveloperExceptionPage();
//默认的HSTS值为30天。您可能希望在生产场景中更改此值,请参阅https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseForwardedHeaders(新ForwardedHeaders选项
{
ForwardedHeaders=Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedProto
});
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(端点=>
{
endpoints.MapDefaultControllerOute();
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage(“/_主机”);
});
}
}
}
编辑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();
   }
}
@page”/test
@继承Models.TestComponent;
试验
@一些测试文本

@代码{ [CascadingParameter]私有AuthenticationStateProvider asp{get;set;} 受保护的重写异步任务OnInitializedAsync() { var authState=wait asp.getAuthenticationStateAncy(); var user=authState.user; 剂量测量(用户); wait base.OnInitializedAsync(); } }

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

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

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

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

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

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped(svc => svc.GetService<IHttpContextAccessor>()?.HttpContext?.User ?? new ClaimsPrincipal());
如果需要在每个razor组件/视图/页面中显示,可以在_ViewImports.cshtml文件中添加@injectstation。此共享视图将添加到所有razor VIE中

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

public class OutsideRazorComponent 
{
    private readonly ClaimsPrincipal _user;

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

}

尝试将@attribute[Authorize]添加到Test的顶部。在我的情况下,使用@inject可以完美地工作。根据Microsoft文档()的说法,这是一种方法。此外,根据文档,您可以注入状态提供程序,而无需级联参数
@inject ClaimsPrincipal User
public class OutsideRazorComponent 
{
    private readonly ClaimsPrincipal _user;

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

}