add jwt parser and auth roles

This commit is contained in:
mfnefd 2024-06-19 22:32:09 +04:00
parent 4d8c2c8a15
commit ff3d4b3824
10 changed files with 187 additions and 9 deletions

70
WebApp/APIClient.cs Normal file
View File

@ -0,0 +1,70 @@
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Text;
namespace WebApp;
public class APIClient
{
private static readonly HttpClient _client = new();
public static void Connect(IConfiguration configuration)
{
_client.BaseAddress = new Uri(configuration["API"]);
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public static T? GetRequest<T>(string requestUrl)
{
var response = _client.GetAsync(requestUrl);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (!response.Result.IsSuccessStatusCode)
{
throw new Exception(response.Result.ReasonPhrase);
}
return JsonConvert.DeserializeObject<T>(result);
}
public static object? PostRequest<T>(string requestUrl, T model)
{
var json = JsonConvert.SerializeObject(model);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = _client.PostAsync(requestUrl, data);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (!response.Result.IsSuccessStatusCode)
{
throw new Exception(response.Result.ReasonPhrase);
}
return result;
}
public static object? DeleteRequest(string requestUrl)
{
var response = _client.DeleteAsync(requestUrl);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (!response.Result.IsSuccessStatusCode)
{
throw new Exception(response.Result.ReasonPhrase);
}
return result;
}
public static object? PatchRequest<T>(string requestUrl, T model)
{
var json = JsonConvert.SerializeObject(model);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = _client.PatchAsync(requestUrl, data);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (!response.Result.IsSuccessStatusCode)
{
throw new Exception(response.Result.ReasonPhrase);
}
return result;
}
}

10
WebApp/Helpers/Roles.cs Normal file
View File

@ -0,0 +1,10 @@
namespace WebApp.Helpers;
public static class Roles
{
public const string User = "Обычный пользователь";
public const string Admin = "Админ";
// TODO: Добавить нужные роли
public const string Worker = "Сотрудник";
}

View File

@ -0,0 +1,9 @@
@page
@model WebApp.Pages.LoginModel
<form method="post">
<input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus name="email">
<input type="password" id="inputPassword" class="form-control" placeholder="Password" required name="password">
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>

View File

@ -0,0 +1,28 @@
using Contracts.BindingModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Newtonsoft.Json;
namespace WebApp.Pages
{
public class LoginModel : PageModel
{
public void OnGet()
{
}
public void OnPostAsync(string email, string password)
{
var response = APIClient.PostRequest("user/login", new { email, password });
if (response is null || response is not string)
{
return;
}
string token = (string)JsonConvert.DeserializeObject((string)response);
// Ñîõðàíÿåì â êóêèñ òîêåí
Response.Cookies.Append("21gunsthebest", token);
Redirect("/");
}
}
}

View File

@ -0,0 +1,2 @@
@page
@model WebApp.Pages.User.SettingsModel

View File

@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using WebApp.Helpers;
namespace WebApp.Pages.User
{
[Authorize(Roles = Roles.Admin + Roles.Worker)]
public class SettingsModel : PageModel
{
public void OnGet()
{
}
}
}

View File

@ -1,8 +1,40 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using WebApp;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["SecretKey"]));
options.TokenValidationParameters = new()
{
ValidateLifetime = true,
IssuerSigningKey = secretKey,
ValidateIssuer = false,
ValidateAudience = false,
};
options.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
// Ïîëó÷àåì èç êóêèñ JWT òîêåí
context.Token = context.Request.Cookies["21gunsthebest"];
return Task.CompletedTask;
}
};
});
builder.Services.AddAuthorization();
// Ïîäêëþ÷àåìñÿ ê API
APIClient.Connect(builder.Configuration);
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@ -18,8 +50,9 @@ app.UseStaticFiles();
app.UseRouting(); app.UseRouting();
app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
app.MapRazorPages(); app.MapRazorPages();
app.Run(); app.Run();

View File

@ -6,4 +6,13 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Contracts\Contracts.csproj" />
</ItemGroup>
</Project> </Project>

View File

@ -3,19 +3,19 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123 VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApp", "WebApp.csproj", "{494318C5-209C-42B9-B15F-BF0D5A8ECF18}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApp", "WebApp.csproj", "{494318C5-209C-42B9-B15F-BF0D5A8ECF18}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinFormsApp", "..\WinFormsApp\WinFormsApp.csproj", "{11F917BB-0ABC-41A0-91B9-B3FD9CEC5277}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinFormsApp", "..\WinFormsApp\WinFormsApp.csproj", "{11F917BB-0ABC-41A0-91B9-B3FD9CEC5277}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestAPI", "..\RestAPI\RestAPI.csproj", "{D3211E26-438E-48B6-9396-2FFC28271DE1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RestAPI", "..\RestAPI\RestAPI.csproj", "{D3211E26-438E-48B6-9396-2FFC28271DE1}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BusinessLogic", "..\BusinessLogic\BusinessLogic.csproj", "{919726B5-89B3-43B3-AA9A-25C1348D86B1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BusinessLogic", "..\BusinessLogic\BusinessLogic.csproj", "{919726B5-89B3-43B3-AA9A-25C1348D86B1}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataModels", "..\DataModels\DataModels.csproj", "{645ED499-8C00-4F04-91FB-A9EF6F1A438E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataModels", "..\DataModels\DataModels.csproj", "{645ED499-8C00-4F04-91FB-A9EF6F1A438E}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contracts", "..\Contracts\Contracts.csproj", "{D7BD8791-F687-460F-8BF7-8F9CD2301EB5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Contracts", "..\Contracts\Contracts.csproj", "{D7BD8791-F687-460F-8BF7-8F9CD2301EB5}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseImplement", "..\DatabaseImplement\DatabaseImplement.csproj", "{527EAA88-4EAF-42D7-93E9-494221351F9C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabaseImplement", "..\DatabaseImplement\DatabaseImplement.csproj", "{527EAA88-4EAF-42D7-93E9-494221351F9C}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -5,5 +5,7 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"API": "https://localhost:7051/",
"SecretKey": "secretkey_secretkey_secretkey_secretkey",
"AllowedHosts": "*" "AllowedHosts": "*"
} }