DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/AuthService.cs

204 lines
6.8 KiB
C#
Raw Normal View History

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;
using Microsoft.EntityFrameworkCore;
using System.Threading;
using System.Threading.Tasks;
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 claimIdUser = "id";
private const string claimNameidCompany = "idCompany";
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 async Task<UserTokenDto> LoginAsync(string login, string password,
CancellationToken token = default)
{
var identity = await GetClaimsUserAsync(login, password, token)
.ConfigureAwait(false);
if (identity == default)
return null;
return new UserTokenDto
{
Id = identity.User.Id,
Name = identity.User.Name,
2021-07-21 15:22:58 +05:00
CompanyName = identity.User.Company.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),
2021-04-23 10:21:25 +05:00
};
}
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;
var salt = GenerateSalt();
var user = new User
{
IdCompany = userDto.IdCompany,
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.AsNoTracking().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;
}
2021-05-19 15:21:19 +05:00
private static 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 async Task<(ClaimsIdentity Identity, User User)> GetClaimsUserAsync(string login,
string password, CancellationToken token = default)
{
var user = await db
.GetUsersByLogin(login)
.AsNoTracking()
.FirstOrDefaultAsync(token)
.ConfigureAwait(false);
if (user is null)
return default;
if (!CheckPassword(user.PasswordHash, password))
return default;
var claims = new List<Claim>
{
new Claim(claimIdUser, user.Id.ToString()),
new Claim(ClaimsIdentity.DefaultNameClaimType, user.Login),
new Claim(ClaimsIdentity.DefaultRoleClaimType, user.Role?.Caption??"GUEST"),
new Claim(claimNameidCompany, user.IdCompany.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;
}
}
}