c# - Blazor 服务器身份验证
问题描述
我想向我的 blazor 服务器端应用程序添加身份验证。我有这个代码可以登录。
var claims = new List<Claim>
{
new Claim(type: ClaimTypes.NameIdentifier, user.Username),
new Claim(type: ClaimTypes.Name, user.Name ?? user.Username),
new Claim(type: ClaimTypes.Sid, user.ID.ToString())
};
if (user.Email != null)
claims.Add(new Claim(type: ClaimTypes.Email, user.Email));
if (user.UserRoles != null)
{
foreach (var userRole in user.UserRoles)
{
claims.Add(new Claim(type: ClaimTypes.Role, userRole.ID_Role));
}
}
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
AllowRefresh = _authModel.Value.AllowRefresh,
ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(_authModel.Value.LoginExpirationMinutes),
IsPersistent = input.IsPersistent
};
await _httpContextAccessor.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);
一切看起来都很好。代码正常运行。但是当我观看 HttpContext.User 或 AuthenticationStateProvider 时,它是空的。在资源管理器中,我看不到 cookie。我做什么坏事?非常感谢你
解决方案
身份验证是您的 Blazor 应用程序内部还是您正在执行任何 API 访问?
通常,您将转交给 SPA 身份验证提供程序的外部人员,然后他们使用该HttpContext.User
组回调您的 SPA。然后默认AuthenticationStateProvider
从 读取用户数据HttpContext.User
。
您在 SPA 内部进行身份验证。启动页面已加载并HttpContext.User
已设置。我不确定您是否可以重置它。您可以编写自定义AuthenticationStateProvider
. 看看我对问题 Custom AuthenticationStateProvider in blazor project doesn't work on server side的回答, 它显示了如何构建测试AuthenticationStateProvider
。您应该能够将其与您的代码一起插入。
更新
这是一个非常愚蠢AuthenticationStateProvider
的,为两个固定用户提供身份验证。从一个按钮呼叫ChangeIdentity
切换。您无需尝试对HttpContext
.
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Blazor.Auth.Test
{
public class DumbAuthenticationStateProvider : AuthenticationStateProvider
{
public static ClaimsPrincipal User
=> new ClaimsPrincipal(new ClaimsIdentity(UserClaims, "Dumb Auth Type"));
public static Claim[] UserClaims
=> new[]{
new Claim(ClaimTypes.Sid, "024672e0-250a-46fc-bd35-1902974cf9e1"),
new Claim(ClaimTypes.Name, "Normal User"),
new Claim(ClaimTypes.NameIdentifier, "Normal User"),
new Claim(ClaimTypes.Email, "user@user,com"),
new Claim(ClaimTypes.Role, "User")
};
public static ClaimsPrincipal Visitor
=> new ClaimsPrincipal(new ClaimsIdentity(VisitorClaims, "Dumb Auth Type"));
public static Claim[] VisitorClaims
=> new[]{
new Claim(ClaimTypes.Sid, "324672e0-250a-46fc-bd35-1902974cf9e1"),
new Claim(ClaimTypes.Name, "Visitor"),
new Claim(ClaimTypes.NameIdentifier, "Normal Visitor"),
new Claim(ClaimTypes.Email, "visitor@user,com"),
new Claim(ClaimTypes.Role, "Visitor")
};
bool _switch;
public override Task<AuthenticationState> GetAuthenticationStateAsync()
=> Task.FromResult(_switch
? new AuthenticationState(User)
: new AuthenticationState(Visitor)
);
public Task<AuthenticationState> ChangeIdentity()
{
_switch = !_switch;
var task = this.GetAuthenticationStateAsync();
this.NotifyAuthenticationStateChanged(task);
return task;
}
}
}
StartUp 中的服务设置:
services.AddScoped<AuthenticationStateProvider, DumbAuthenticationStateProvider>();
services.AddAuthorizationCore();
<button class="btn btn-dark" @onclick="ChangeID">Switch</button>
@code {
[Inject] private AuthenticationStateProvider authenticationStateProvider {get; set;}
private DumbAuthenticationStateProvider myAuthenticationStateProvider => authenticationStateProvider as DumbAuthenticationStateProvider;
private async Task ChangeID()
{
await myAuthenticationStateProvider.ChangeIdentity();
}
}
基于应用程序的 GitHub 副本的第二次更新。
首先,您需要确保在AuthenticationStateProvider
之后加载新的ServerSideBlazor
(它会加载ServerAuthenticationSateProvider
重载之前加载的任何内容)并清理 StartUp:
{
//services.AddAuthentication(
// CookieAuthenticationDefaults.AuthenticationScheme)
// .AddCookie();
// services.AddAuthorization();
//services.AddScoped<AuthenticationStateProvider>(provider => provider.GetRequiredService<DumbAuthenticationStateProvider>());
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<AuthenticationStateProvider, DumbAuthenticationStateProvider>();
services.AddAuthorizationCore();
services.AddSingleton<WeatherForecastService>();
}
更新 App.razor - 更改RouteView
为AuthorizeRouteView
.
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
我的测试页面
@page "/fetchdata"
@using Microsoft.AspNetCore.Components.Authorization
@using WebApplication6.Data
<AuthorizeView>
<Authorized>
<div class="m-2 p-2">
<a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
</div>
</Authorized>
</AuthorizeView>
<button class="btn btn-dark" @onclick="ChangeID">Switch</button>
@code {
[Inject] private AuthenticationStateProvider authenticationStateProvider { get; set; }
private DumbAuthenticationStateProvider myAuthenticationStateProvider => authenticationStateProvider as DumbAuthenticationStateProvider;
private async Task ChangeID()
{
await myAuthenticationStateProvider.ChangeIdentity();
}
}
推荐阅读
- xml - dotnet core REST API 发布数据无法从请求中的列表中读取 XML
- javascript - 在 javascript 中访问我的 json 响应的元素
- windows - 如何使用十六进制编辑器删除突出显示的代码行?
- hadoop - 卡在 ambari 2.6.2 中的应用时间线服务器安装
- java - Android Studio Activity 启动延迟
- security - 被浏览器拒绝的二级域的通配符 SSL/TLS 证书
- c# - 无法通过c#将数据从ms访问传到mysql
- java - 无法将 zookeeper 对象转换为 json,反之亦然
- c - 在 C++ 中 abs( *a - *b) 不返回负数的绝对值
- r - 循环一个函数,该函数返回由另一个变量分组的数据框中的变量列表