216 lines
6.8 KiB
C#
216 lines
6.8 KiB
C#
using System.Security.Claims;
|
|
using GozareshgirProgramManager.Application._Common.Interfaces;
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
namespace GozareshgirProgramManager.Infrastructure.Services.Authentication;
|
|
|
|
/// <summary>
|
|
/// سرویس کمکی برای کار با JWT و HttpContext
|
|
/// این کلاس فقط با توکن و Context کار میکند و هیچ عملیات دیتابیسی ندارد
|
|
/// </summary>
|
|
public class AuthHelper : IAuthHelper
|
|
{
|
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
private readonly JwtTokenGenerator _jwtTokenGenerator;
|
|
|
|
public AuthHelper(
|
|
IHttpContextAccessor httpContextAccessor,
|
|
JwtTokenGenerator jwtTokenGenerator)
|
|
{
|
|
_httpContextAccessor = httpContextAccessor;
|
|
_jwtTokenGenerator = jwtTokenGenerator;
|
|
}
|
|
|
|
public LoginSession SignIn(long userId, string userName, string fullName, long accountId, List<string> roles)
|
|
{
|
|
|
|
// 1. تولید Access Token
|
|
var accessToken = GenerateAccessToken(userId, userName, fullName, accountId, roles);
|
|
var accessTokenExpiration = DateTime.Now.AddMinutes(30);
|
|
|
|
// 2. تولید Refresh Token
|
|
var refreshToken = GenerateRefreshToken();
|
|
var refreshTokenExpiration = GetRefreshTokenExpiration();
|
|
|
|
// 3. ذخیره Refresh Token در Cookie
|
|
_httpContextAccessor.HttpContext?.Response.Cookies.Append("rf-token", refreshToken, new CookieOptions
|
|
{
|
|
HttpOnly = true,
|
|
Secure = true,
|
|
SameSite = SameSiteMode.Lax,
|
|
Expires = refreshTokenExpiration
|
|
});
|
|
|
|
// 4. تنظیم Authorization Header (اختیاری - معمولاً کلاینت خودش این کار را میکند)
|
|
_httpContextAccessor.HttpContext?.Response.Headers.Append("Authorization", $"Bearer {accessToken}");
|
|
|
|
return new LoginSession
|
|
{
|
|
AccessToken = accessToken,
|
|
RefreshToken = refreshToken,
|
|
RefreshTokenExpiration = refreshTokenExpiration,
|
|
AccessTokenExpiration = accessTokenExpiration
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// تولید Access Token
|
|
/// </summary>
|
|
public string GenerateAccessToken(long userId, string userName, string fullName, long? accountId, List<string> roles)
|
|
{
|
|
return _jwtTokenGenerator.GenerateAccessToken(userId, userName, fullName, accountId, roles);
|
|
}
|
|
|
|
/// <summary>
|
|
/// تولید Refresh Token
|
|
/// </summary>
|
|
public string GenerateRefreshToken()
|
|
{
|
|
return _jwtTokenGenerator.GenerateRefreshToken();
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت تاریخ انقضای Refresh Token
|
|
/// </summary>
|
|
public DateTime GetRefreshTokenExpiration()
|
|
{
|
|
return _jwtTokenGenerator.GetRefreshTokenExpiration();
|
|
}
|
|
|
|
/// <summary>
|
|
/// اعتبارسنجی توکن و استخراج Claims
|
|
/// </summary>
|
|
public ClaimsPrincipal? ValidateToken(string token)
|
|
{
|
|
return _jwtTokenGenerator.ValidateToken(token);
|
|
}
|
|
|
|
/// <summary>
|
|
/// اعتبارسنجی توکن منقضی شده (بدون چک زمان)
|
|
/// </summary>
|
|
public ClaimsPrincipal? ValidateExpiredToken(string token)
|
|
{
|
|
return _jwtTokenGenerator.ValidateExpiredToken(token);
|
|
}
|
|
|
|
/// <summary>
|
|
/// استخراج UserId از توکن (حتی اگر منقضی شده باشد)
|
|
/// </summary>
|
|
public long? GetUserIdFromToken(string token)
|
|
{
|
|
try
|
|
{
|
|
var principal = _jwtTokenGenerator.ValidateExpiredToken(token);
|
|
if (principal == null) return null;
|
|
|
|
var userIdClaim = principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
return long.TryParse(userIdClaim, out var userId) ? userId : null;
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت اطلاعات IP کاربر جاری
|
|
/// </summary>
|
|
public string? GetClientIpAddress()
|
|
{
|
|
return _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress?.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت User Agent کاربر جاری
|
|
/// </summary>
|
|
public string? GetUserAgent()
|
|
{
|
|
return _httpContextAccessor.HttpContext?.Request.Headers["User-Agent"].ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت Refresh Token از Header
|
|
/// </summary>
|
|
public string? GetRefreshTokenFromCookie()
|
|
{
|
|
return _httpContextAccessor.HttpContext?.Request.Cookies["rf-token"];
|
|
}
|
|
|
|
/// <summary>
|
|
/// بررسی احراز هویت کاربر جاری
|
|
/// </summary>
|
|
public bool IsAuthenticated()
|
|
{
|
|
return _httpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت شناسه کاربر جاری از Claims
|
|
/// </summary>
|
|
public long? GetCurrentUserId()
|
|
{
|
|
var userIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirst("pm.userId")?.Value;
|
|
return long.TryParse(userIdClaim, out var userId) ? userId : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت نام کاربری جاری از Claims
|
|
/// </summary>
|
|
public string? GetCurrentUserName()
|
|
{
|
|
return _httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.Name)?.Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت نام کامل کاربر جاری از Claims
|
|
/// </summary>
|
|
public string? GetCurrentFullName()
|
|
{
|
|
return _httpContextAccessor.HttpContext?.User?.FindFirst("FullName")?.Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت AccountId کاربر جاری از Claims
|
|
/// </summary>
|
|
public long? GetCurrentAccountId()
|
|
{
|
|
var accountIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirst("AccountId")?.Value;
|
|
return long.TryParse(accountIdClaim, out var accountId) ? accountId : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت نقشهای کاربر جاری از Claims
|
|
/// </summary>
|
|
public List<string> GetCurrentUserRoles()
|
|
{
|
|
var roles = _httpContextAccessor.HttpContext?.User?.FindAll(ClaimTypes.Role)
|
|
.Select(c => c.Value)
|
|
.ToList();
|
|
|
|
return roles ?? new List<string>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// بررسی دسترسی کاربر به نقش خاص
|
|
/// </summary>
|
|
public bool HasRole(string roleName)
|
|
{
|
|
return _httpContextAccessor.HttpContext?.User?.IsInRole(roleName) ?? false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// بررسی دسترسی کاربر به یکی از نقشها
|
|
/// </summary>
|
|
public bool HasAnyRole(params string[] roleNames)
|
|
{
|
|
return roleNames.Any(HasRole);
|
|
}
|
|
|
|
public void SignOut()
|
|
{
|
|
_httpContextAccessor.HttpContext?.Response.Cookies.Delete("rf-token");
|
|
_httpContextAccessor.HttpContext?.Response.Headers.Remove("Authorization");
|
|
}
|
|
}
|
|
|