C# 如何访问.razor文件之外的AuthorizationProvider?
我有一个带有razor组件的apsnet核心应用程序。我使用Discord OAuth进行登录,可以读取.razor文件中的声明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; <
@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;
}
}