Код: Выделить всё
@page "/auth"
@rendermode InteractiveServer
@using System.Text.RegularExpressions
@using System.ComponentModel.DataAnnotations
@inject IHttpClientFactory HttpClientFactory
@inject NavigationManager Navigation
...
@code {
...
private async Task LoginAsync()
{
await form.Validate();
if (!success) return;
var client = HttpClientFactory.CreateClient("server");
var content = new FormUrlEncodedContent(new Dictionary
{
{ "email", loginEmail },
{ "password", loginPassword }
});
var response = await client.PostAsync("api/auth/login", content);
if (!response.IsSuccessStatusCode)
{
errors = new[] { "Неверный адрес эл. почты или пароль" };
return;
}
Navigation.NavigateTo("/", true);
}
}
Код: Выделить всё
[ApiController]
[Route("api/auth")]
public class AuthController : Controller
{
private readonly BarberchainDbContext _db;
public AuthController(BarberchainDbContext db)
{
_db = db;
}
[HttpPost]
[Route("login")]
public async Task Login([FromForm] string email, [FromForm] string password)
{
var acc = _db.Accounts.FirstOrDefault(a => a.Email == email);
if (acc == null)
{
return BadRequest("Invalid login or email");
}
var hashString = System.Text.Encoding.UTF8.GetString(acc.Hash);
if (!BCrypt.Net.BCrypt.Verify(password, hashString))
{
return BadRequest("Invalid login or email");
}
var claims = new List
{
new Claim(ClaimTypes.NameIdentifier, acc.Id.ToString()),
new Claim(ClaimTypes.Name, acc.Email ?? ""),
new Claim(ClaimTypes.Role, acc.Role.ToString())
};
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
principal,
new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.AddDays(7)
}
);
return Ok();
}
...
}
Код: Выделить всё
@using barberchainAPI.Components.Layout
@using Microsoft.AspNetCore.Components.Authorization
Код: Выделить всё
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddDbContext(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"),
o => o.MapEnum("account_role")));
builder.Services.AddMudServices();
builder.Services.AddControllers();
builder.Services.AddHttpClient("server", client =>
{
client.BaseAddress = new Uri("https://localhost:7027/");
});
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(x =>
{
x.LoginPath = "/auth";
});
builder.Services.AddAuthorization();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped();
builder.Services.AddScoped();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();
app.MapControllers();
app.MapRazorComponents()
.AddInteractiveServerRenderMode();
app.Run();
}
Обратите внимание, как AuthPage.razor использует @rendermode InteractiveServer. Я рассмотрел аналогичный вопрос здесь о переполнении стека, и человек, который ответил, сказал, что режим рендеринга должен быть статическим SSR (я думаю, статический рендеринг на стороне сервера). Режим рендеринга «InteractiveServer», очевидно, является противоположным. Однако, когда я удаляю режим рендеринга (я предполагаю, что это SSR, если он не указан), страница становится статичной, и кнопки не реагируют на мои нажатия. Возможно, эта директива @rendermode и является причиной всех проблем из-за особенностей режима рендеринга InteractiveServer. Может быть, мне стоит переключиться на другой режим рендеринга? К какому? Почему?
Подробнее здесь: https://stackoverflow.com/questions/798 ... -net-8-app
Мобильная версия