forked from ddrilling/AsbCloudServer
202 lines
6.7 KiB
C#
202 lines
6.7 KiB
C#
using AsbCloudApp.Data;
|
|
using AsbCloudApp.Services;
|
|
using AsbCloudDb.Model;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Linq;
|
|
using System.Security.Claims;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace AsbCloudInfrastructure.Services
|
|
{
|
|
public class AuthService : IAuthService
|
|
{
|
|
private readonly IAsbCloudDbContext db;
|
|
|
|
public const string issuer = "a";
|
|
public const string audience = "a";
|
|
public static readonly SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("супер секретный ключ для шифрования"));
|
|
public const string algorithms = SecurityAlgorithms.HmacSha256;
|
|
|
|
private static readonly TimeSpan expiresTimespan = TimeSpan.FromDays(365.25);
|
|
private static readonly Encoding encoding = Encoding.UTF8;
|
|
private const int PasswordSaltLength = 5;
|
|
private const string claimNameIdCustomer = "IdCustomer";
|
|
private readonly HashAlgorithm hashAlgoritm;
|
|
private readonly Random rnd;
|
|
|
|
public AuthService(IAsbCloudDbContext db)
|
|
{
|
|
this.db = db;
|
|
hashAlgoritm = SHA384.Create();
|
|
rnd = new Random((int)(DateTime.Now.Ticks % 2147480161));
|
|
}
|
|
|
|
public UserTokenDto Login(string login, string password)
|
|
{
|
|
var identity = GetClaimsUser(login, password);
|
|
if (identity == default)
|
|
return null;
|
|
|
|
return new UserTokenDto
|
|
{
|
|
Id = identity.User.Id,
|
|
Name = identity.User.Name,
|
|
CustomerName = identity.User.Customer.Caption,
|
|
Level = identity.User.Level,
|
|
Login = identity.User.Login,
|
|
Patronymic = identity.User.Patronymic,
|
|
RoleName = identity.User.Role.Caption,
|
|
Surname = identity.User.Surname,
|
|
Token = MakeToken(identity.Identity.Claims),
|
|
};
|
|
}
|
|
|
|
public string Refresh(ClaimsPrincipal user)
|
|
{
|
|
return MakeToken(user.Claims);
|
|
}
|
|
|
|
public int Register(UserDto userDto)
|
|
{
|
|
if (userDto.Login.Length < 3)
|
|
return -1;
|
|
|
|
if (userDto.Password.Length < 3)
|
|
return -2;
|
|
|
|
//if (db.Customers.FirstOrDefault(c=>c.Id == userDto.IdCustomer) is null)
|
|
// return -3;
|
|
|
|
//if (db.UserRoles.FirstOrDefault(c => c.Id == userDto.IdRole) is null)
|
|
// return -4;
|
|
|
|
//if (db.Users.FirstOrDefault(c => c.Login == userDto.Login) != null)
|
|
// return -5;
|
|
|
|
var salt = GenerateSalt();
|
|
|
|
var user = new User
|
|
{
|
|
IdCustomer = userDto.IdCustomer,
|
|
IdRole = userDto.IdRole,
|
|
Name = userDto.Name,
|
|
Surname = userDto.Surname,
|
|
Patronymic = userDto.Patronymic,
|
|
Level = userDto.Level,
|
|
Login = userDto.Login,
|
|
PasswordHash = salt + ComputeHash(salt, userDto.Password)
|
|
};
|
|
|
|
db.Users.Add(user);
|
|
try
|
|
{
|
|
db.SaveChanges();
|
|
}
|
|
catch //(Exception ex)
|
|
{
|
|
return -6;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public int ChangePassword(string userLogin, string newPassword)
|
|
{
|
|
var user = db.Users.FirstOrDefault(u => u.Login == userLogin);
|
|
if (user == null)
|
|
return -1;
|
|
|
|
var salt = GenerateSalt();
|
|
user.PasswordHash = salt + ComputeHash(salt, newPassword);
|
|
db.SaveChanges();
|
|
return 0;
|
|
}
|
|
|
|
public int ChangePassword(int idUser, string newPassword)
|
|
{
|
|
var user = db.Users.FirstOrDefault(u => u.Id == idUser);
|
|
if (user == null)
|
|
return -1;
|
|
|
|
var salt = GenerateSalt();
|
|
user.PasswordHash = salt + ComputeHash(salt, newPassword);
|
|
db.SaveChanges();
|
|
return 0;
|
|
}
|
|
|
|
private string MakeToken(IEnumerable<Claim> claims)
|
|
{
|
|
var now = DateTime.Now;
|
|
|
|
var jwt = new JwtSecurityToken(
|
|
issuer: issuer,
|
|
audience: audience,
|
|
notBefore: now,
|
|
claims: claims,
|
|
expires: now.Add(expiresTimespan),
|
|
signingCredentials: new SigningCredentials(securityKey, algorithms));
|
|
|
|
return new JwtSecurityTokenHandler().WriteToken(jwt);
|
|
}
|
|
|
|
private (ClaimsIdentity Identity, User User) GetClaimsUser(string login, string password)
|
|
{
|
|
var user = db
|
|
.GetUsersByLogin(login)
|
|
.FirstOrDefault();
|
|
|
|
if (user is null)
|
|
return default;
|
|
|
|
if (!CheckPassword(user.PasswordHash, password))
|
|
return default;
|
|
|
|
var claims = new List<Claim>
|
|
{
|
|
new Claim(ClaimsIdentity.DefaultNameClaimType, user.Login),
|
|
new Claim(ClaimsIdentity.DefaultRoleClaimType, user.Role?.Caption??"GUEST"),
|
|
new Claim(claimNameIdCustomer, user.IdCustomer.ToString()),
|
|
};
|
|
var claimsIdentity = new ClaimsIdentity(claims, "Token", ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);
|
|
return (claimsIdentity, user);
|
|
}
|
|
|
|
private bool CheckPassword(string passwordHash, string password)
|
|
{
|
|
if (passwordHash.Length == 0 && password.Length == 0)
|
|
return true;
|
|
|
|
if (passwordHash.Length < PasswordSaltLength)
|
|
return false;
|
|
|
|
var salt = passwordHash[0..PasswordSaltLength];
|
|
var hashDb = passwordHash[PasswordSaltLength..];
|
|
|
|
return hashDb == ComputeHash(salt, password);
|
|
}
|
|
|
|
private string ComputeHash(string salt, string password)
|
|
{
|
|
var hashBytes = hashAlgoritm.ComputeHash(encoding.GetBytes(salt + password));
|
|
var hashString = BitConverter.ToString(hashBytes)
|
|
.Replace("-", "")
|
|
.ToLower();
|
|
return hashString;
|
|
}
|
|
|
|
public string GenerateSalt()
|
|
{
|
|
const string saltChars = "sHwiaX7kZT1QRp0cPILGUuK2Sz=9q8lmejDNfoYCE3B_WtgyVv6M5OxAJ4Frbhnd";
|
|
string salt = "";
|
|
for (int i = 0; i < PasswordSaltLength - 1; i++)
|
|
salt += saltChars[rnd.Next(0, saltChars.Length)];
|
|
salt += "|";
|
|
return salt;
|
|
}
|
|
}
|
|
}
|