Egy kis authentikáció
This commit is contained in:
@@ -7,12 +7,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkFlowCheck.API", "WorkFl
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.NFC", "Plugin.NFC\Plugin.NFC.csproj", "{6B46795C-DF5A-4F12-95A9-691BC1741AB8}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.NFC", "Plugin.NFC\Plugin.NFC.csproj", "{6B46795C-DF5A-4F12-95A9-691BC1741AB8}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkFlowCheck.MAUI", "WorkFlowCheck.MAUI\WorkFlowCheck.MAUI.csproj", "{0E2BD120-EE91-4A24-A78A-CE7CA87E09AE}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkFlowCheck.DL", "WorkFlowCheck.DL\WorkFlowCheck.DL.csproj", "{25A8C0E7-18C7-4672-ABE8-29596E7E9B72}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkFlowCheck.DL", "WorkFlowCheck.DL\WorkFlowCheck.DL.csproj", "{25A8C0E7-18C7-4672-ABE8-29596E7E9B72}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkFlowCheck.BL", "WorkFlowCheck.BL\WorkFlowCheck.BL.csproj", "{73049F81-7A5D-4819-ADB8-A9926672365E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkFlowCheck.BL", "WorkFlowCheck.BL\WorkFlowCheck.BL.csproj", "{73049F81-7A5D-4819-ADB8-A9926672365E}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkFlowCheck.Common", "WorkFlowCheck.Common\WorkFlowCheck.Common.csproj", "{7F94D6CB-3358-4687-88E1-FA46053D6B71}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -27,12 +27,6 @@ Global
|
|||||||
{6B46795C-DF5A-4F12-95A9-691BC1741AB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6B46795C-DF5A-4F12-95A9-691BC1741AB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6B46795C-DF5A-4F12-95A9-691BC1741AB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6B46795C-DF5A-4F12-95A9-691BC1741AB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6B46795C-DF5A-4F12-95A9-691BC1741AB8}.Release|Any CPU.Build.0 = Release|Any CPU
|
{6B46795C-DF5A-4F12-95A9-691BC1741AB8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{0E2BD120-EE91-4A24-A78A-CE7CA87E09AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{0E2BD120-EE91-4A24-A78A-CE7CA87E09AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{0E2BD120-EE91-4A24-A78A-CE7CA87E09AE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
|
||||||
{0E2BD120-EE91-4A24-A78A-CE7CA87E09AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{0E2BD120-EE91-4A24-A78A-CE7CA87E09AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{0E2BD120-EE91-4A24-A78A-CE7CA87E09AE}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
|
||||||
{25A8C0E7-18C7-4672-ABE8-29596E7E9B72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{25A8C0E7-18C7-4672-ABE8-29596E7E9B72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{25A8C0E7-18C7-4672-ABE8-29596E7E9B72}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{25A8C0E7-18C7-4672-ABE8-29596E7E9B72}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{25A8C0E7-18C7-4672-ABE8-29596E7E9B72}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{25A8C0E7-18C7-4672-ABE8-29596E7E9B72}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@@ -41,6 +35,10 @@ Global
|
|||||||
{73049F81-7A5D-4819-ADB8-A9926672365E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{73049F81-7A5D-4819-ADB8-A9926672365E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{73049F81-7A5D-4819-ADB8-A9926672365E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{73049F81-7A5D-4819-ADB8-A9926672365E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{73049F81-7A5D-4819-ADB8-A9926672365E}.Release|Any CPU.Build.0 = Release|Any CPU
|
{73049F81-7A5D-4819-ADB8-A9926672365E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7F94D6CB-3358-4687-88E1-FA46053D6B71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7F94D6CB-3358-4687-88E1-FA46053D6B71}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7F94D6CB-3358-4687-88E1-FA46053D6B71}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7F94D6CB-3358-4687-88E1-FA46053D6B71}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using WorkFlowCheck.BL.DTO;
|
using WorkFlowCheck.Common.DTO;
|
||||||
using WorkFlowCheck.BL.Services.Interfaces;
|
using WorkFlowCheck.BL.Services.Interfaces;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace WorkFlowCheck.API.Controllers
|
namespace WorkFlowCheck.API.Controllers
|
||||||
{
|
{
|
||||||
@@ -47,5 +48,53 @@ namespace WorkFlowCheck.API.Controllers
|
|||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("authenticate")]
|
||||||
|
public async Task<ApiResponseDTO<UserDTO>> Authenticate([FromBody] UserDTO userDTO)
|
||||||
|
{
|
||||||
|
var retVal = new ApiResponseDTO<UserDTO>()
|
||||||
|
{
|
||||||
|
IsSuccess = true
|
||||||
|
};
|
||||||
|
if (string.IsNullOrEmpty(userDTO.UserName) || string.IsNullOrEmpty(userDTO.Password))
|
||||||
|
{
|
||||||
|
retVal.IsSuccess = false;
|
||||||
|
retVal.Errors.Add("Nem megfelelő felhasználói név vagy jelszó");
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var userDTO_Response = await _userService.Authenticate(userDTO.UserName, userDTO.Password);
|
||||||
|
if (userDTO_Response != null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(userDTO_Response.UserName) == false && userDTO_Response.UserName == userDTO.UserName)
|
||||||
|
{
|
||||||
|
retVal.IsSuccess = true;
|
||||||
|
retVal.Data = userDTO_Response;
|
||||||
|
Log.Information($"Sikeres azonosítás! {userDTO.UserName}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var error = $"Nem megfelelő felhasználó vagy jelszó! {userDTO.UserName}";
|
||||||
|
retVal.IsSuccess = false;
|
||||||
|
retVal.Errors.Add(error);
|
||||||
|
Log.Information(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var error = $"Nem megfelelő felhasználó vagy jelszó! {userDTO.UserName}";
|
||||||
|
retVal.IsSuccess = false;
|
||||||
|
retVal.Errors.Add(error);
|
||||||
|
Log.Information(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
Log.Error(ex.Message);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Serilog;
|
using Serilog;
|
||||||
using WorkFlowCheck.BL.Mappings;
|
using WorkFlowCheck.BL.Mappings;
|
||||||
using WorkFlowCheck.BL.Infra;
|
using WorkFlowCheck.BL.Infra;
|
||||||
|
using WorkFlowCheck.DL.Seed;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@@ -77,6 +78,12 @@ builder.Services.AddControllers()
|
|||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
DBInitializer.Seed(context);
|
||||||
|
}
|
||||||
|
|
||||||
// Swagger middleware
|
// Swagger middleware
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using AutoMapper.Configuration.Conventions;
|
using AutoMapper.Configuration.Conventions;
|
||||||
using WorkFlowCheck.BL.DTO;
|
using WorkFlowCheck.Common.DTO;
|
||||||
using WorkFlowCheck.DL.Entities;
|
using WorkFlowCheck.DL.Entities;
|
||||||
|
|
||||||
namespace WorkFlowCheck.BL.Mappings
|
namespace WorkFlowCheck.BL.Mappings
|
||||||
@@ -15,6 +15,9 @@ namespace WorkFlowCheck.BL.Mappings
|
|||||||
public MapperProfile()
|
public MapperProfile()
|
||||||
{
|
{
|
||||||
CreateMap<User, UserDTO>();
|
CreateMap<User, UserDTO>();
|
||||||
|
CreateMap<UserDTO, User>()
|
||||||
|
.ForMember(dest => dest.PasswordHash, opt => opt.MapFrom<PasswordHashResolver>());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using WorkFlowCheck.Common.DTO;
|
||||||
|
using WorkFlowCheck.Common.Security;
|
||||||
|
using WorkFlowCheck.DL.Entities;
|
||||||
|
|
||||||
|
namespace WorkFlowCheck.BL.Mappings
|
||||||
|
{
|
||||||
|
public class PasswordHashResolver : IValueResolver<UserDTO, User, string>
|
||||||
|
{
|
||||||
|
public string Resolve(UserDTO source, User destination, string destMember, ResolutionContext context)
|
||||||
|
{
|
||||||
|
return PasswordHasher.HashPassword(source.Password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,13 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using WorkFlowCheck.BL.DTO;
|
using WorkFlowCheck.Common.DTO;
|
||||||
|
|
||||||
namespace WorkFlowCheck.BL.Services.Interfaces
|
namespace WorkFlowCheck.BL.Services.Interfaces
|
||||||
{
|
{
|
||||||
public interface IUserService
|
public interface IUserService
|
||||||
{
|
{
|
||||||
Task<UserDTO> GetUser(int Id);
|
Task<UserDTO> GetUser(int Id);
|
||||||
|
Task<UserDTO> Authenticate(string UserName, string Password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using WorkFlowCheck.BL.DTO;
|
using WorkFlowCheck.Common.DTO;
|
||||||
using WorkFlowCheck.BL.Services.Interfaces;
|
using WorkFlowCheck.BL.Services.Interfaces;
|
||||||
using WorkFlowCheck.DL;
|
using WorkFlowCheck.DL;
|
||||||
|
using WorkFlowCheck.Common.Security;
|
||||||
|
|
||||||
namespace WorkFlowCheck.BL.Services
|
namespace WorkFlowCheck.BL.Services
|
||||||
{
|
{
|
||||||
@@ -39,5 +40,24 @@ namespace WorkFlowCheck.BL.Services
|
|||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<UserDTO> Authenticate(string userName, string password)
|
||||||
|
{
|
||||||
|
var retVal = new UserDTO();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var user = await _dbContext.Users.Where(w => w.UserName == userName).FirstOrDefaultAsync();
|
||||||
|
if (user != null && PasswordHasher.VerifyPassword(user.PasswordHash, password))
|
||||||
|
{
|
||||||
|
retVal = _mapper.Map<UserDTO>(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex.Message);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\WorkFlowCheck.Common\WorkFlowCheck.Common.csproj" />
|
||||||
<ProjectReference Include="..\WorkFlowCheck.DL\WorkFlowCheck.DL.csproj" />
|
<ProjectReference Include="..\WorkFlowCheck.DL\WorkFlowCheck.DL.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -6,5 +6,7 @@
|
|||||||
public string Email { get; set; } = null!;
|
public string Email { get; set; } = null!;
|
||||||
public string FirstName { get; set; } = null!;
|
public string FirstName { get; set; } = null!;
|
||||||
public string LastName { get; set; } = null!;
|
public string LastName { get; set; } = null!;
|
||||||
|
public string UserName { get;set; } = null!;
|
||||||
|
public string Password { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WorkFlowCheck.Common.Security
|
||||||
|
{
|
||||||
|
public static class PasswordHasher
|
||||||
|
{
|
||||||
|
// Jelszó hashelése
|
||||||
|
public static string HashPassword(string password)
|
||||||
|
{
|
||||||
|
// Generate a random salt
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
using (var rng = RandomNumberGenerator.Create())
|
||||||
|
{
|
||||||
|
rng.GetBytes(salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash the password with the salt
|
||||||
|
using (var rfc2898 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256))
|
||||||
|
{
|
||||||
|
byte[] hash = rfc2898.GetBytes(32); // 256-bit hash
|
||||||
|
byte[] hashBytes = new byte[48]; // Salt (16 bytes) + Hash (32 bytes)
|
||||||
|
Array.Copy(salt, 0, hashBytes, 0, 16);
|
||||||
|
Array.Copy(hash, 0, hashBytes, 16, 32);
|
||||||
|
|
||||||
|
return Convert.ToBase64String(hashBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jelszó ellenőrzése
|
||||||
|
public static bool VerifyPassword(string storedPasswordHash, string inputPassword)
|
||||||
|
{
|
||||||
|
byte[] hashBytes = Convert.FromBase64String(storedPasswordHash);
|
||||||
|
|
||||||
|
// Extract salt (first 16 bytes) and stored hash (next 32 bytes)
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
byte[] storedHash = new byte[32];
|
||||||
|
Array.Copy(hashBytes, 0, salt, 0, 16);
|
||||||
|
Array.Copy(hashBytes, 16, storedHash, 0, 32);
|
||||||
|
|
||||||
|
// Hash the input password with the same salt
|
||||||
|
using (var rfc2898 = new Rfc2898DeriveBytes(inputPassword, salt, 10000, HashAlgorithmName.SHA256))
|
||||||
|
{
|
||||||
|
byte[] inputHash = rfc2898.GetBytes(32);
|
||||||
|
|
||||||
|
// Compare the stored hash and the calculated hash
|
||||||
|
return CryptographicOperations.FixedTimeEquals(storedHash, inputHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,5 +8,7 @@ namespace WorkFlowCheck.DL.Entities
|
|||||||
public string Email { get; set; } = null!;
|
public string Email { get; set; } = null!;
|
||||||
public string FirstName { get; set; } = null!;
|
public string FirstName { get; set; } = null!;
|
||||||
public string LastName { get; set; } = null!;
|
public string LastName { get; set; } = null!;
|
||||||
|
public string UserName { get; set; } = null!;
|
||||||
|
public string PasswordHash { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WorkFlowCheck.DL.Seed
|
||||||
|
{
|
||||||
|
public static class DBInitializer
|
||||||
|
{
|
||||||
|
public static void Seed(AppDbContext dbContext)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user