121 lines
3.5 KiB
C#
121 lines
3.5 KiB
C#
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Security.Claims;
|
||
|
|
using System.Security.Cryptography;
|
||
|
|
using System.Text;
|
||
|
|
using System.Threading.Tasks;
|
||
|
|
using SkyArtShop.Models;
|
||
|
|
|
||
|
|
namespace SkyArtShop.Services;
|
||
|
|
|
||
|
|
public class PostgreAuthService
|
||
|
|
{
|
||
|
|
private readonly PostgreSQLService _pgService;
|
||
|
|
|
||
|
|
public PostgreAuthService(PostgreSQLService pgService)
|
||
|
|
{
|
||
|
|
_pgService = pgService;
|
||
|
|
}
|
||
|
|
|
||
|
|
public string HashPassword(string password)
|
||
|
|
{
|
||
|
|
using RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
|
||
|
|
byte[] array = new byte[16];
|
||
|
|
randomNumberGenerator.GetBytes(array);
|
||
|
|
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, array, 10000, HashAlgorithmName.SHA256);
|
||
|
|
byte[] bytes = rfc2898DeriveBytes.GetBytes(32);
|
||
|
|
byte[] array2 = new byte[48];
|
||
|
|
Array.Copy(array, 0, array2, 0, 16);
|
||
|
|
Array.Copy(bytes, 0, array2, 16, 32);
|
||
|
|
return Convert.ToBase64String(array2);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool VerifyPassword(string password, string hashedPassword)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (hashedPassword.Contains(':'))
|
||
|
|
{
|
||
|
|
string[] array = hashedPassword.Split(':');
|
||
|
|
if (array.Length != 3)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
int iterations = int.Parse(array[0]);
|
||
|
|
byte[] salt = Convert.FromBase64String(array[1]);
|
||
|
|
byte[] array2 = Convert.FromBase64String(array[2]);
|
||
|
|
byte[] array3 = Rfc2898DeriveBytes.Pbkdf2(Encoding.UTF8.GetBytes(password), salt, iterations, HashAlgorithmName.SHA256, array2.Length);
|
||
|
|
return CryptographicOperations.FixedTimeEquals(array2, array3);
|
||
|
|
}
|
||
|
|
byte[] array4 = Convert.FromBase64String(hashedPassword);
|
||
|
|
byte[] array5 = new byte[16];
|
||
|
|
Array.Copy(array4, 0, array5, 0, 16);
|
||
|
|
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, array5, 10000, HashAlgorithmName.SHA256);
|
||
|
|
byte[] bytes = rfc2898DeriveBytes.GetBytes(32);
|
||
|
|
for (int i = 0; i < 32; i++)
|
||
|
|
{
|
||
|
|
if (array4[i + 16] != bytes[i])
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<AdminUser?> AuthenticateAsync(string email, string password)
|
||
|
|
{
|
||
|
|
AdminUser user = await _pgService.GetUserByEmailAsync(email);
|
||
|
|
if (user == null || !VerifyPassword(password, user.PasswordHash))
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
await _pgService.UpdateUserLastLoginAsync(user.Id, DateTime.UtcNow);
|
||
|
|
user.LastLogin = DateTime.UtcNow;
|
||
|
|
return user;
|
||
|
|
}
|
||
|
|
|
||
|
|
public ClaimsPrincipal CreateClaimsPrincipal(AdminUser user)
|
||
|
|
{
|
||
|
|
List<Claim> list = new List<Claim>
|
||
|
|
{
|
||
|
|
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", user.Id),
|
||
|
|
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", user.Email),
|
||
|
|
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", user.Name),
|
||
|
|
new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", user.Role)
|
||
|
|
};
|
||
|
|
foreach (string permission in user.Permissions)
|
||
|
|
{
|
||
|
|
list.Add(new Claim("Permission", permission));
|
||
|
|
}
|
||
|
|
ClaimsIdentity identity = new ClaimsIdentity(list, "Cookies");
|
||
|
|
return new ClaimsPrincipal(identity);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<AdminUser?> GetUserByEmailAsync(string email)
|
||
|
|
{
|
||
|
|
return await _pgService.GetUserByEmailAsync(email);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<AdminUser> CreateUserAsync(string email, string password, string name, string role = "Admin")
|
||
|
|
{
|
||
|
|
AdminUser user = new AdminUser
|
||
|
|
{
|
||
|
|
Id = Guid.NewGuid().ToString(),
|
||
|
|
Email = email,
|
||
|
|
PasswordHash = HashPassword(password),
|
||
|
|
Name = name,
|
||
|
|
Role = role,
|
||
|
|
IsActive = true,
|
||
|
|
CreatedAt = DateTime.UtcNow,
|
||
|
|
Permissions = new List<string>()
|
||
|
|
};
|
||
|
|
await _pgService.CreateAdminUserAsync(user);
|
||
|
|
return user;
|
||
|
|
}
|
||
|
|
}
|