如何在Blazor服务器应用程序中注入claimprincipal



这里有一些工件可以帮助理解这个问题:

  • 示例代码- Github repo
  • 已部署的应用程序-不再可用

更新:我已经跟随了这个YouTube视频,我现在认为这是正确的方式来访问有关Blazor服务器应用程序的依赖服务中已认证用户的信息:https://www.youtube.com/watch?v=Eh4xPgP5PsM.

我已经更新了Github代码来反映这个解决方案。


我有以下类,我在我的ASP中使用依赖注入注册。. NET MVC核心应用。

public class UserContext
{
ClaimsPrincipal _principal;
public UserContext(ClaimsPrincipal principal) => _principal = principal;
public bool IsAuthenticated => _principal.Identity.IsAuthenticated;
}

public class WrapperService
{
UserContext _userContext; 
public WrapperService(UserContext context) => _userContext = context;
public bool UserHasSpecialAccess() 
{
return _userContext.IsAuthenticated;
}
}

在Startup.cs

中配置IoC依赖项注册
services.AddScoped<ClaimsPrincipal>(x =>
{
var context = x.GetRequiredService<IHttpContextAccessor>();
return context.HttpContext.User;
});
services.AddScoped<UserContext>();
services.AddScoped<WrapperService>();

我最近在MVC应用程序中启用了Blazor,并希望在我的Blazor组件中使用我的DI注册服务。

我将服务注入到Blazor组件中,以便像这样使用它:

@inject WrapperService _Wrapper

然而,当我试图从服务器端处理程序中使用服务时,请求失败,异常抱怨服务无法构建-由于IHttpContext不存在于后续对服务器的调用。

<button @onclick="HandleClick">Check Access</button>
async Task HandleClick()
{
var hasPermission = _Wrapper.UserHasSpecialAccess(); // fails 😔
}

我想我明白为什么在Blazor服务器应用程序中使用IHttpContextAccessor不工作/推荐。我的问题是,如果没有它,我如何访问我在服务中需要的索赔?

对我来说奇怪的是,当我在开发环境中的IIS Express下运行它时,这一切都有效,但当我部署并试图从Azure AppService中运行它时失败了。

这就是我的工作,为AuthenticationStateProvider编写一个派生类。

public class AppAuthenticationStateProvider : AuthenticationStateProvider
{
private ClaimsPrincipal principal;
// Constructor, only needed when injections required
public AppAuthenticationStateProvider(/* INJECTIONS HERE */)
: base()
{
principal ??= new();
}
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
return Task.FromResult(new AuthenticationState(principal));
}
// Method called from login form view
public async Task LogIn(/* USER AND PASSWORD */)
{
// Create session
principal = new ClaimsPrincipal(...);
var task = Task.FromResult(new AuthenticationState(principal));
NotifyAuthenticationStateChanged(task);
}
// Method called from logout form view
public async Task LogOut()
{
// Close session
principal = new();
var task = Task.FromResult(new AuthenticationState(principal));
NotifyAuthenticationStateChanged(task);
}

然后,在程序/启动时添加这些行:

// Example for .Net 6
builder.Services.AddScoped<AuthenticationStateProvider, AppAuthenticationStateProvider>();
builder.Services.AddScoped<ClaimsPrincipal>(s =>
{
var stateprovider = s.GetRequiredService<AuthenticationStateProvider>();
var state = stateprovider.GetAuthenticationStateAsync().Result;
return state.User;
});

就是这样。现在你可以在任何你想要的地方注入claimprincipal了。

你可以将AuthenticationStateProvider注入到你的Service构造函数中,然后使用

var principal = await _authenticationStateProvider.GetAuthenticationStateAsync();

AuthenticationStateProvider是一个有作用域的服务,所以你的也必须是。

使用CascadingAuthenticationState访问声明主体

https://learn.microsoft.com/en us/aspnet/core/blazor/security/?view=aspnetcore - 5.0 # expose-the-authentication-state-as-a-cascading-parameter-1

如果您需要使用自己的逻辑,则需要实现自己的身份验证状态提供程序。

如果你想使用一个服务来使用claimprincipal,你可以这样做:

ClaimsPrincipalUserService.cs

ClaimsPrincipal claimsPrincipal;
void SetClaimsPrincipal(ClaimsPrincipal cp)
{
claimsPrincipal = cp;
// any logic + notifications which need to be raised when 
// ClaimsPrincipal has changes
}

在启动时注入这个服务。

在布局

MainLayout.razor
@inject ClaimsPrincipalUserService cpus;
[CascadingParameter]
public Task<AuthenticationState> State {get;set;}
protected override async Task OnInitializedAsync()
{
var state = await State;
var user = state.User; // Get claims principal.
cpus.SetClaimsPrincipal(user);
}

相关内容

  • 没有找到相关文章

最新更新