c# - Blazor,自定义身份验证,然后基于授权策略
问题描述
我正在创建一个 blazor 服务器端应用程序,我添加了一个 CustomAuthenticationStateProvider 并通过会话检查用户是否仍然处于活动状态等等。接下来我添加了一个基于策略的控件,因此我检查用户是否有权访问某个区域或执行某个操作。我注意到如果我使用@attribute [Authorize(Policy = "Insert_receipt")] 应用程序不再进入 CustomAuthenticationStateProvider,这样它就不会更新用户的状态以防发生变化。我必须强制重新加载页面 (F5) 才能重新进入 CustomAuthenticationStateProvider。
我在剃刀页面上试过这个
@attribute [Authorize]
@attribute [Authorize(Policy = "Insert_receipt")]
但是应用程序忽略了第一个,它只检查用户是否有策略。
我也试过这个
@attribute [Authorize]
<h3>ReceiptEntry</h3>
<AuthorizeView Policy = "Insert_receipt">
<Authorized>
<p>Create</p>
<p>@IdVehicle</p>
@if (User != null) {
<p>@User.Username</p>
}
@if (User2 != null) {
<p>@User2.Username</p>
}
</Authorized>
</AuthorizeView>
但什么都没有,这行不通。
CustomAuthenticationStateProvider.cs
public class CustomAuthenticationStateProvider : AuthenticationStateProvider {
private ISessionStorageService _sessionStorageService;
private int _exp_date = 1;
private UserLoginService _userService = new UserLoginService();
public CustomAuthenticationStateProvider(ISessionStorageService sessionStorageService) {
_sessionStorageService = sessionStorageService;
}
/// <summary>
/// </summary>
/// <returns></returns>
public override async Task<AuthenticationState> GetAuthenticationStateAsync() {
UserLogged User = null;
//var username = await _sessionStorageService.GetItemAsync<UserLogged>("User");
var token = await _sessionStorageService.GetItemAsync<string>("User");
if (token != null) {
try {
var u = Utility.Decrypt(token);
User = JsonConvert.DeserializeObject<UserLogged>(u);
DateTime dt = User.Expired_date;
User = _userService.GetUserLogged(User.Username);
User.Expired_date = dt;
} catch (Exception) {
await _sessionStorageService.RemoveItemAsync("User");
}
}
ClaimsIdentity identity;
if (User != null) {
if (User.Expired_date > DateTime.Now) {
// correggo l'ora della scadenza
User.Expired_date = DateTime.Now.AddDays(_exp_date);
var serializeObject = JsonConvert.SerializeObject(User);
var encrSerializeObject = Utility.Encrypt(serializeObject);
await _sessionStorageService.SetItemAsync("User", encrSerializeObject);
Claim encryptClaim = new Claim("Data", encrSerializeObject);
Claim userClaim = new Claim("User", serializeObject);
//identity = new ClaimsIdentity(new[] {
// new Claim(ClaimTypes.Name,User.Username),
// encryptClaim
//}, "auth_type");
identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name,User.Username),
encryptClaim,
userClaim
}, "auth_type");
} else {
//time session closed
identity = new ClaimsIdentity();
}
} else {
identity = new ClaimsIdentity();
//identity = null;
}
var user = new ClaimsPrincipal(identity);
if (!user.Identity.IsAuthenticated) {
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}
return await Task.FromResult(new AuthenticationState(user));
}
/// <summary>
/// si notifica il cambiamento di stato, l utente é autentificato
/// </summary>
/// <param name="email"></param>
public void MarkAuthenticationStateChanged(string username) {
UserLogged userLogged = _userService.GetUserLogged(username);
userLogged.Expired_date = DateTime.Now.AddDays(_exp_date);
var serializeObject = JsonConvert.SerializeObject(userLogged);
var encrSerializeObject = Utility.Encrypt(serializeObject);
Claim encryptClaim = new Claim("Data", encrSerializeObject);
Claim userClaim = new Claim("User", serializeObject);
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name,userLogged.Username),
encryptClaim,
userClaim
}, "auth_type");
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
_sessionStorageService.SetItemAsync("User", encrSerializeObject);
}
/// <summary>
/// si notifica il cambiamento di stato, l utente é autentificato
/// </summary>
/// <param name="email"></param>
public void MarkAuthenticationStateChanged(UserLogged userLogged, string encrSerializeObject, string serializeObject) {
Claim encryptClaim = new Claim("Data", encrSerializeObject);
Claim userClaim = new Claim("User", serializeObject);
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name,userLogged.Username),
encryptClaim,
userClaim
}, "auth_type");
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}
public void MarkUserAsLoggedOut() {
_sessionStorageService.RemoveItemAsync("User");
var identity = new ClaimsIdentity();
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}
}
CustomActionHandler.cs
public class CustomActionHandler : AuthorizationHandler<CustomActionRequirement> {
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomActionRequirement requirement) {
if (!context.User.HasClaim(c => c.Type == "User")) {
return Task.CompletedTask;
}
var user = context.User.FindFirst(c => c.Type == "User").Value;
if (user != null) {
var userLogged = JsonConvert.DeserializeObject<UserLogged>(user);
if (userLogged.Actions.Contains(requirement.authorized_Action)) {
context.Succeed(requirement);
}
}
return Task.CompletedTask;
}
}
启动.cs
//custom auth
services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
//custom policy for AuthorizeView Policy for action
foreach (Authorized_action action in Enum.GetValues(typeof(Authorized_action))) {
services.AddAuthorization(options => {
options.AddPolicy(action.ToString(), policy =>
policy.Requirements.Add(new CustomActionRequirement(action)));
});
}
services.AddSingleton<IAuthorizationHandler, CustomActionHandler>();
...
app.UseAuthentication();
app.UseAuthorization();
MainLayout.razor
<AuthorizeView>
<Authorized>
<MudLayout>
<MudAppBar Elevation="1">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@((e) => DrawerToggle())" />
<MudText Typo="Typo.h5" Class="ml-3">Application</MudText>
</MudAppBar>
<MudDrawer @bind-Open="_drawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2">
<NavMenu />
</MudDrawer>
<MudMainContent>
<MudContainer Class="mt-16 px-8" MaxWidth="MaxWidth.False">
@Body
</MudContainer>
</MudMainContent>
</MudLayout>
</Authorized>
<NotAuthorized>
@if (true) { NavManager.NavigateTo(""); }
</NotAuthorized>
</AuthorizeView>
解决方案
推荐阅读
- wix - 从 WiX 中的 64 位 MSI 包写入 32 位目录的 hack
- r - 在 Rshiny Dashboaord 上生成饼图
- flutter - 颤振中permission_handler包的未定义名称“权限”
- docker - 带有本地执行程序的 Airflow 2.0 Docker 设置
- unreal-engine4 - 如何在虚幻引擎4中启用鼠标在播放模式下移动对象
- javascript - 如何在 Facebook 上检索我所有的朋友和我朋友的朋友?
- html - 未找到 jinja2 模板 - 未解决
- java - 如何从文件中读取文本并替换丢失的数据?
- java - 在 NetBeans 8.2 IDE 开发程序中使用 javamail 将 3 个文件发送给收件人
- mysql - Xampp安装和.frm文件上的Mysql致命错误