fix authorize

This commit is contained in:
2025-12-05 00:27:43 +08:00
parent bd95848972
commit 00dd4fa958
18 changed files with 300 additions and 168 deletions

View File

@@ -0,0 +1,90 @@
@inherits ComponentBase
<CascadingAuthenticationState>
<AuthorizeView Context="authContext">
<Authorized>
@if (_isAuthorized)
{
@ChildContent
}
else if (!string.IsNullOrEmpty(NotAuthorizedContent))
{
@NotAuthorizedContent
}
</Authorized>
<NotAuthorized>
@if (!string.IsNullOrEmpty(NotAuthenticatedContent))
{
@NotAuthenticatedContent
}
</NotAuthorized>
</AuthorizeView>
</CascadingAuthenticationState>
@code {
[CascadingParameter] private Task<AuthenticationState>? AuthenticationStateTask { get; set; }
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public string? NotAuthorizedContent { get; set; }
[Parameter] public string? NotAuthenticatedContent { get; set; }
[Parameter] public string? Permission { get; set; } // 单个权限
[Parameter] public string[]? AnyPermissions { get; set; } // 多个权限
[Parameter] public string[]? Roles { get; set; } // 多个角色
[Parameter] public string? Policy { get; set; } // 策略名称
private bool _isAuthorized = false;
protected override async Task OnInitializedAsync()
{
// 如果 Claims 中没有权限信息,使用 PermissionService 异步检查
if (AuthenticationStateTask != null)
{
var authState = await AuthenticationStateTask;
var user = authState.User;
if (user.Identity?.IsAuthenticated ?? false)
{
var userPermissions = user.Claims.Where(c => c.Type == ClaimKeys.Permission).Select(c => c.Value).SingleOrDefault()?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList();
if(userPermissions == null)
{
userPermissions = new List<string>();
}
// 检查单个权限
if (Roles?.Length > 0)
{
var hasRole = Roles.Any(role => user.IsInRole(role));
if (!hasRole)
{
_isAuthorized = true;
return;
}
}
if (!string.IsNullOrEmpty(Permission))
{
var hasAllPermissions = userPermissions.Contains(Permission);
if (hasAllPermissions)
{
_isAuthorized = true;
return;
}
}
if (AnyPermissions?.Length > 0)
{
var hasAnyPermission = AnyPermissions.Any(p => userPermissions.Contains(p));
if (!hasAnyPermission)
{
_isAuthorized = true;
return;
}
}
}
else
{
_isAuthorized = false;
}
}
}
}

View File

@@ -1,121 +0,0 @@
@using Microsoft.AspNetCore.Authorization
@using System.Security.Claims
@inject IPermissionService PermissionService
@inject IAuthorizationService AuthorizationService
<CascadingAuthenticationState>
<AuthorizeView Context="authContext">
<Authorized>
@if (_hasPermission)
{
@ChildContent
}
else if (!string.IsNullOrEmpty(NotAuthorizedContent))
{
@NotAuthorizedContent
}
</Authorized>
<NotAuthorized>
@if (!string.IsNullOrEmpty(NotAuthenticatedContent))
{
@NotAuthenticatedContent
}
</NotAuthorized>
</AuthorizeView>
</CascadingAuthenticationState>
@code {
[CascadingParameter] Task<AuthenticationState>? AuthenticationStateTask { get; set; }
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public string? Permission { get; set; }
[Parameter] public string[]? Permissions { get; set; }
[Parameter] public bool RequireAll { get; set; }
[Parameter] public string? Policy { get; set; }
[Parameter] public string? NotAuthorizedContent { get; set; }
[Parameter] public string? NotAuthenticatedContent { get; set; }
private bool _hasPermission;
protected override async Task OnParametersSetAsync()
{
_hasPermission = false;
var authState = AuthenticationStateTask is null
? await Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())))
: await AuthenticationStateTask;
var user = authState.User;
if (user?.Identity is null || !user.Identity.IsAuthenticated)
{
_hasPermission = false;
return;
}
// 优先基于声明快速判断(适用于 Server 与 WASM
if (!string.IsNullOrEmpty(Permission))
{
if (user.Claims.Any(c => c.Type == ClaimKeys.Permission && c.Value == Permission))
{
_hasPermission = true;
return;
}
// 回退:调用后端权限服务(适用于 Server-side 权限来源于数据库)
_hasPermission = await SafeHasPermissionAsync(Permission);
return;
}
if (Permissions != null && Permissions.Length > 0)
{
var userPermissions = user.Claims.Where(c => c.Type == ClaimKeys.Permission).Select(c => c.Value).ToHashSet();
if (RequireAll)
{
if (Permissions.All(p => userPermissions.Contains(p)))
{
_hasPermission = true;
return;
}
}
else
{
if (Permissions.Any(p => userPermissions.Contains(p)))
{
_hasPermission = true;
return;
}
}
// 回退:调用后端权限服务
if (RequireAll)
_hasPermission = await PermissionService.HasAllPermissionsAsync(Permissions);
else
_hasPermission = await PermissionService.HasAnyPermissionAsync(Permissions);
return;
}
if (!string.IsNullOrEmpty(Policy))
{
// 使用 AuthorizationService 并传入当前用户
var result = await AuthorizationService.AuthorizeAsync(user, Policy);
_hasPermission = result.Succeeded;
return;
}
}
private async Task<bool> SafeHasPermissionAsync(string permission)
{
try
{
return await PermissionService.HasPermissionAsync(permission);
}
catch
{
// 出错时默认拒绝
return false;
}
}
}

View File

@@ -19,6 +19,9 @@
DefaultValue="umi ui"
Options="DefaultOptions" />
</SpaceItem> *@
<SpaceItem>
<Text Type="TextElementType.Warning">@handler</Text>
</SpaceItem>
<SpaceItem>
<AntDesign.Tooltip Title="@("Help")" Placement="@Placement.Bottom">
<Unbound>
@@ -62,6 +65,8 @@
@code {
string handler = "Server";
private ErrorBoundary? _errorBoundary;
private void ResetError(Exception ex)
@@ -105,6 +110,14 @@
protected async override Task OnInitializedAsync()
{
if (OperatingSystem.IsBrowser())
{
handler = "Wasm";
}
else
{
handler = "Server";
}
var url = "/api/menu/tree";
var apiResult = await HttpService.Get<ApiResult<List<MenuDataItem>>>(url);

View File

@@ -119,9 +119,21 @@ else
var token = dprop.TryGetProperty("token", out var t) ? t.GetString() ?? string.Empty : string.Empty;
var refresh = dprop.TryGetProperty("refreshToken", out var r) ? r.GetString() ?? string.Empty : string.Empty;
// WASM 的 localStorage 在 Server Circuit 中无意义,这里不用写 localStorage。
// WASM 的 localStorage 在 Server Circuit 中无意义,兼容auto模式写入 localStorage。
try
{
await localStorage.SetItemAsync(StorageKeys.AccessToken, token);
await localStorage.SetItemAsync(StorageKeys.RefreshToken, refresh);
if (AuthStateProvider is PersistentAuthenticationStateProvider provider)
{
provider.UpdateAuthenticationState(token);
}
}
catch { }
// 浏览器已通过 fetch 收到 Set-Cookie强制重载使 Circuit 使用新 Cookie。
Logger.LogInformation("登录成功server 跳转: {ReturnUrl}", ReturnUrl);
Logger.LogInformation($"登录成功server 跳转: {ReturnUrl}");
Navigation.NavigateTo(ReturnUrl ?? "/", forceLoad: true);
}
else

View File

@@ -24,7 +24,7 @@
}
catch { /* 忽略网络错误,仍继续清理客户端状态 */ }
if (AuthStateProvider is Atomx.Admin.Client.Utils.PersistentAuthenticationStateProvider provider)
if (AuthStateProvider is PersistentAuthenticationStateProvider provider)
{
await provider.MarkUserAsLoggedOut();
}
@@ -41,6 +41,14 @@
var success = jsResult.ValueKind == JsonValueKind.Object && jsResult.TryGetProperty("success", out var sp) && sp.GetBoolean();
Logger.LogInformation("Server logout result: {Success}", success);
try
{
// 清理 localStorage如果有的话
await localStorage.RemoveItemAsync(StorageKeys.AccessToken);
await localStorage.RemoveItemAsync(StorageKeys.RefreshToken);
}
catch { }
// 尽管我们可能已经处理了服务器态,强制重新加载确保 Circuit 更新
Navigation.NavigateTo("/account/login", forceLoad: true);
}

View File

@@ -32,17 +32,9 @@
<Flex Justify="FlexJustify.SpaceBetween">
帐号列表
<div>
<AuthorizePermissionView Permission="@Permissions.User.Create">
<AuthorizeCheck Permission="@Permissions.Admin.Create">\
<Button Class="me-3" OnClick="OnCreateClick" Type="ButtonType.Primary">新增</Button>
</AuthorizePermissionView>
@* <AuthorizeView Policy="@Permissions.Admin.Edit">
<Authorized>
<Button Class="me-3" OnClick="OnCreateClick" Type="ButtonType.Primary">新增</Button>
</Authorized>
<NotAuthorized>
没有权限
</NotAuthorized>
</AuthorizeView> *@
</AuthorizeCheck>
</div>
</Flex>
</TitleTemplate>
@@ -182,7 +174,7 @@
{
loadQueryString();
LoadList();
_ = LoadList();
base.OnParametersSet();
}
@@ -213,28 +205,34 @@
}
private async void LoadList()
private async Task LoadList()
{
loading = true;
var url = "/api/admin/search";
var apiResult = await HttpService.GetPagingList<Admin>(url, search, Page.GetValueOrDefault(1), PageSize.GetValueOrDefault(20));
if (apiResult.Success)
try
{
if (apiResult.Data != null)
var apiResult = await HttpService.GetPagingList<Admin>(url, search, Page.GetValueOrDefault(1), PageSize.GetValueOrDefault(20));
if (apiResult.Success)
{
PagingList = apiResult.Data;
if (apiResult.Data != null)
{
PagingList = apiResult.Data;
}
}
}
loading = false;
StateHasChanged();
finally
{
loading = false;
StateHasChanged();
}
}
private void OnReset()
{
search = new();
LoadList();
_ = LoadList();
}
void OnSearchReset()
@@ -298,7 +296,7 @@
var apiResult = await HttpService.Post<ApiResult<string>>(url, new());
if (apiResult.Success)
{
LoadList();
_ = LoadList();
await ModalService.InfoAsync(new ConfirmOptions() { Title = "操作提示", Content = "删除数据成功" });
}
else

View File

@@ -1,8 +1,11 @@
using Atomx.Common.Models;
using Atomx.Utils.Json;
using System.Net.Http.Json;
using System.Text;
using Microsoft.AspNetCore.Http;
using System.Net;
using System.Net.Http.Json;
using System.Security.Claims;
using System.Text;
using System.Text.Json;
namespace Atomx.Admin.Client.Services
{
@@ -10,11 +13,13 @@ namespace Atomx.Admin.Client.Services
{
private readonly HttpClient _httpClient;
private readonly IHttpContextAccessor? _httpContextAccessor;
private readonly ILogger<HttpService> _logger;
public HttpService(HttpClient httpClient, IHttpContextAccessor? httpContextAccessor = null)
public HttpService(HttpClient httpClient, IHttpContextAccessor? httpContextAccessor = null, ILogger<HttpService>? logger = null)
{
_httpClient = httpClient;
_httpContextAccessor = httpContextAccessor;
_logger = logger ?? Microsoft.Extensions.Logging.Abstractions.NullLogger<HttpService>.Instance;
}
public async Task<T> Get<T>(string url)
@@ -29,6 +34,8 @@ namespace Atomx.Admin.Client.Services
}
else
{
await LogNonSuccessAsync(url, response);
ThrowForStatus(response.StatusCode, url);
throw new Exception($"Error: {response.StatusCode}");
}
}
@@ -50,6 +57,8 @@ namespace Atomx.Admin.Client.Services
}
else
{
await LogNonSuccessAsync(url, response);
ThrowForStatus(response.StatusCode, url);
throw new Exception($"Error: {response.StatusCode}");
}
}
@@ -78,13 +87,16 @@ namespace Atomx.Admin.Client.Services
}
else
{
// 明确抛 Unauthorized 以便上层按需处理
throw new Exception($"Error: {response.StatusCode}");
await LogNonSuccessAsync(url, response);
// 明确在 401/403 场景抛出授权异常以便上层 UI/组件做特殊处理
ThrowForStatus(response.StatusCode, url);
throw new Exception($"Error: {response.StatusCode}");
}
}
catch (HttpRequestException ex)
{
Console.WriteLine(ex.ToString());
_logger.LogError(ex, "HttpRequestException while calling {Url}", url);
Console.Error.WriteLine($"[{DateTime.UtcNow:o}] HttpRequestException Url:{url} Error:{ex.Message}");
throw new Exception($"api {url} service failure");
}
}
@@ -115,5 +127,64 @@ namespace Atomx.Admin.Client.Services
// 忽略任何转发异常,保持健壮性
}
}
private async Task LogNonSuccessAsync(string url, HttpResponseMessage response)
{
try
{
var status = response.StatusCode;
var reason = response.ReasonPhrase;
string userId = "unknown";
string ip = "unknown";
var ctx = _httpContextAccessor?.HttpContext;
if (ctx != null)
{
userId = ctx.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value
?? ctx.User?.FindFirst("sub")?.Value
?? "unknown";
if (ctx.Request.Headers.TryGetValue("X-Forwarded-For", out var xff) && !string.IsNullOrWhiteSpace(xff))
{
ip = xff.ToString().Split(',')[0].Trim();
}
else
{
ip = ctx.Connection.RemoteIpAddress?.ToString() ?? "unknown";
}
}
// 结构化日志记录
_logger.LogWarning("UserId:{UserId} Url:{Url} Ip:{Ip} HttpStatus:{StatusCode} Reason:{ReasonPhrase}", userId, url, ip, (int)status, reason);
// 控制台输出一份,便于本地/容器查看
var consoleMsg = new
{
Timestamp = DateTime.UtcNow.ToString("o"),
Level = "Warning",
UserId = userId,
Url = url,
Ip = ip,
Status = (int)status,
Reason = reason
};
Console.WriteLine(JsonSerializer.Serialize(consoleMsg));
}
catch (Exception ex)
{
// 日志失败不能影响主流程
_logger.LogError(ex, "Failed to log non-success response for {Url}", url);
}
}
private void ThrowForStatus(HttpStatusCode statusCode, string url)
{
if (statusCode == HttpStatusCode.Unauthorized || statusCode == HttpStatusCode.Forbidden)
{
// 抛出明确的授权异常,便于上层按需处理(例如提示登陆、重定向或显示权限不足)
throw new UnauthorizedAccessException($"Error: {statusCode} when calling {url}");
}
}
}
}

View File

@@ -29,7 +29,7 @@ namespace Atomx.Admin.Client.Utils
{
var claims = new List<Claim>
{
new(ClaimKeys.Id, userInfo.Id.ToString()),
new(ClaimKeys.UId, userInfo.Id.ToString()),
new(ClaimKeys.Name, userInfo.Name),
new(ClaimKeys.Email, userInfo.Email),
new(ClaimKeys.Mobile, userInfo.MobilePhone),
@@ -79,7 +79,7 @@ namespace Atomx.Admin.Client.Utils
{
var claims = new List<Claim>
{
new(ClaimKeys.Id, customUserClaims.Id.ToString()),
new(ClaimKeys.UId, customUserClaims.Id.ToString()),
new(ClaimKeys.Name, customUserClaims.Name),
new(ClaimKeys.Email, customUserClaims.Email),
new(ClaimKeys.Mobile, customUserClaims.MobilePhone),
@@ -114,7 +114,7 @@ namespace Atomx.Admin.Client.Utils
var handler = new JwtSecurityTokenHandler();
var token = handler.ReadJwtToken(jwtToken);
var id = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Id)?.Value ?? string.Empty;
var id = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.UId)?.Value ?? string.Empty;
var name = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Name)?.Value ?? string.Empty;
var email = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Email)?.Value ?? string.Empty;
var phone = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Mobile)?.Value ?? string.Empty;

View File

@@ -1,5 +1,6 @@
@using System.Net.Http
@using System.Net.Http.Json
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms

View File

@@ -11,11 +11,11 @@
<link rel="stylesheet" href="@Assets["Atomx.Admin.styles.css"]" />
<ImportMap />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet @rendermode="InteractiveServer" />
<HeadOutlet @rendermode="InteractiveAuto" />
</head>
<body>
<Routes @rendermode="InteractiveServer" />
<Routes @rendermode="InteractiveAuto" />
<script src="_framework/blazor.web.js"></script>
</body>

View File

@@ -1,11 +1,13 @@
using Atomx.Admin.Client.Models;
using Atomx.Admin.Client.Validators;
using Atomx.Admin.Services;
using Atomx.Common.Constants;
using Atomx.Common.Models;
using Atomx.Data;
using Atomx.Data.Services;
using Atomx.Utils.Extension;
using MapsterMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@@ -13,6 +15,7 @@ namespace Atomx.Admin.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class AdminController : ControllerBase
{
readonly ILogger<AdminController> _logger;
@@ -46,6 +49,7 @@ namespace Atomx.Admin.Controllers
/// <param name="size"></param>
/// <returns></returns>
[HttpPost("search")]
[Authorize(Policy =Permissions.Admin.View)]
public IActionResult Search(AdminSearch search, int page, int size = 20)
{
var startTime = search.RangeTime[0];

View File

@@ -182,6 +182,8 @@ namespace Atomx.Admin.Controllers
try
{
int count = _dbContext.SaveChanges();
//刷新缓存
await _cacheService.GetRoleById(data.Id,true);
result = result.IsSuccess(count.ToString());
}
catch (Exception ex)

View File

@@ -120,7 +120,7 @@ namespace Atomx.Admin.Controllers
var role = _dbContext.Roles.SingleOrDefault(p => p.Id == user.RoleId);
var claims = new List<Claim>
{
new Claim(ClaimKeys.Id, user.Id.ToString()),
new Claim(ClaimKeys.UId, user.Id.ToString()),
new Claim(ClaimKeys.Email, user.Email ?? string.Empty),
new Claim(ClaimKeys.Name, user.Username ?? string.Empty),
new Claim(ClaimKeys.Role, user.RoleId.ToString()),
@@ -201,8 +201,8 @@ namespace Atomx.Admin.Controllers
Path = "/"
};
Response.Cookies.Append("accessToken", accessToken, cookieOptions);
Response.Cookies.Append("refreshToken", refreshToken, cookieOptions);
Response.Cookies.Append(StorageKeys.AccessToken, accessToken, cookieOptions);
Response.Cookies.Append(StorageKeys.RefreshToken, refreshToken, cookieOptions);
return new JsonResult(new ApiResult<AuthResponse>().IsSuccess(authResponse));
}
@@ -261,7 +261,7 @@ namespace Atomx.Admin.Controllers
var role = _dbContext.Roles.SingleOrDefault(p => p.Id == user.RoleId);
var claims = new List<Claim>
{
new Claim(ClaimKeys.Id, user.Id.ToString()),
new Claim(ClaimKeys.UId, user.Id.ToString()),
new Claim(ClaimKeys.Email, user.Email ?? string.Empty),
new Claim(ClaimKeys.Name, user.Username ?? string.Empty),
new Claim(ClaimKeys.Role, user.RoleId.ToString()),
@@ -324,8 +324,8 @@ namespace Atomx.Admin.Controllers
Path = "/"
};
Response.Cookies.Append("accessToken", accessToken, cookieOptions);
Response.Cookies.Append("refreshToken", refreshToken, cookieOptions);
Response.Cookies.Append(StorageKeys.AccessToken, accessToken, cookieOptions);
Response.Cookies.Append(StorageKeys.RefreshToken, refreshToken, cookieOptions);
return new JsonResult(new ApiResult<AuthResponse>().IsSuccess(authResponse));
@@ -391,8 +391,8 @@ namespace Atomx.Admin.Controllers
Path = "/"
};
Response.Cookies.Append("accessToken", string.Empty, expiredOptions);
Response.Cookies.Append("refreshToken", string.Empty, expiredOptions);
Response.Cookies.Append(StorageKeys.AccessToken, string.Empty, expiredOptions);
Response.Cookies.Append(StorageKeys.RefreshToken, string.Empty, expiredOptions);
}
catch (Exception ex)
{

View File

@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Atomx.Common.Constants;
using Atomx.Data.Services;
using Microsoft.AspNetCore.Mvc;
using System.Net;
using System.Text.Json;
@@ -35,9 +37,60 @@ namespace Atomx.Admin.Middlewares
}
}
private static string GetRequestUserId(HttpContext ctx)
{
var user = ctx.User;
return user?.FindFirst(ClaimKeys.UId)?.Value
?? user?.FindFirst("sub")?.Value
?? "unknown";
}
private static string GetRequestUrl(HttpContext ctx)
{
return $"{ctx.Request.Method} {ctx.Request.Path}{ctx.Request.QueryString}";
}
private static string GetClientIp(HttpContext ctx)
{
if (ctx.Request.Headers.TryGetValue("X-Forwarded-For", out var xff) && !string.IsNullOrWhiteSpace(xff))
{
return xff.ToString().Split(',')[0].Trim();
}
return ctx.Connection.RemoteIpAddress?.ToString() ?? "unknown";
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
_logger.LogError(exception, "未处理的异常: {Message}", exception.Message);
// 额外收集请求上下文信息
var userId = GetRequestUserId(context);
var url = GetRequestUrl(context);
var ip = GetClientIp(context);
// 结构化日志ILogger
_logger.LogError(exception, "UserId:{UserId} Url:{Url} Ip:{Ip} Error:{Message}", userId, url, ip, exception.Message);
// 同时输出到控制台(便于本地/容器日志查看)
try
{
var consoleMsg = new
{
Timestamp = DateTime.UtcNow.ToString("o"),
Level = "Error",
UserId = userId,
Url = url,
Ip = ip,
Message = exception.Message,
Exception = exception.GetType().FullName,
StackTrace = exception.StackTrace,
InnerException = exception.InnerException?.Message
};
// 简单 JSON 输出,便于日志聚合和搜索
Console.Error.WriteLine(JsonSerializer.Serialize(consoleMsg));
}
catch
{
// 忽略控制台写入异常,确保原始异常处理继续
}
var response = context.Response;
response.ContentType = "application/json";

View File

@@ -180,6 +180,7 @@ app.UseAuthorization();
app.UseAntiforgery();
app.MapStaticAssets();
app.UseMiddleware<MonitoringMiddleware>();
app.UseMiddleware<ExceptionHandlingMiddleware>();
// SignalR endpoints<74><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD> Hub<75><62><EFBFBD><EFBFBD><EFBFBD>ڴ˴<DAB4>ӳ<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Hub <20><><EFBFBD><EFBFBD> ChatHub<75><62>NotificationHub<75><62><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ȡ<EFBFBD><C8A1>ע<EFBFBD>Ͳ<EFBFBD>ӳ<EFBFBD><D3B3>

View File

@@ -64,7 +64,7 @@ namespace Atomx.Admin.Services
//var userIdClaim = _httpContextAccessor.HttpContext?.User.FindFirst(ClaimKeys.Id);
//return userIdClaim != null ? long.Parse(userIdClaim.Value) : 0;
var id = _httpContextAccessor.HttpContext?.User?.Claims?.SingleOrDefault(p => p.Type == ClaimKeys.Id)?.Value ?? "0";
var id = _httpContextAccessor.HttpContext?.User?.Claims?.SingleOrDefault(p => p.Type == ClaimKeys.UId)?.Value ?? "0";
return id.ToLong();
}

View File

@@ -96,7 +96,7 @@ namespace Atomx.Admin.Utils
if (principal.Identity?.IsAuthenticated == true)
{
var id = principal.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Id)?.Value ?? string.Empty;
var id = principal.Claims.SingleOrDefault(x => x.Type == ClaimKeys.UId)?.Value ?? string.Empty;
var name = principal.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Name)?.Value ?? string.Empty;
var email = principal.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Email)?.Value ?? string.Empty;
var phone = principal.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Mobile)?.Value ?? string.Empty;

View File

@@ -2,7 +2,7 @@
{
public static class ClaimKeys
{
public const string Id = "id";
public const string UId = "sub";
public const string CorporationId = "cid";
public const string Name = "name";
public const string Email = "email";