Как интегрировать LDAP с веб-приложением Blazor на базе .NET 8 (серверная сторона)?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Как интегрировать LDAP с веб-приложением Blazor на базе .NET 8 (серверная сторона)?

Сообщение Anonymous »

Я пытаюсь интегрировать аутентификацию с нашим сервером LDAP для веб-приложения .NET 8 Blazor.
Мой файл launchSettings.json
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:25412",
"sslPort": 44310,
"environmentVariables": {
"UserDomains": "mycorp=LDAP://mycorp.com"
}
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5102",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"UserDomains": "mycorp=LDAP://mycorp.com"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7038;http://localhost:5102",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"UserDomains": "mycorp=LDAP://mycorp.com"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"UserDomains": "mycorp=LDAP://mycorp.com"
}
}
}
}

UserLogin.razor
@page "/userlogin"
@using System.ComponentModel.DataAnnotations
@using System.Text
@using System.DirectoryServices
@using RCBuisinessLogic
@using RCBuisinessLogic.Authentication
@using RCWebApp.Models
@rendermode InteractiveServer
@inject IHttpContextAccessor HttpContextAccessor
@inject NavigationManager NavigationManager
@inject UserInformation UserInformation






Username:



Password:



Login



@code {
private Login Login { get; set; } = new Login();

private async Task HandleLogin()
{
string userDomains = Environment.GetEnvironmentVariable("UserDomains");
bool isValidLogin = IsValidLogin("LDAP://mycorp.com", "mycorp", Login.UserName, Login.Password, out string retMessage);
if (isValidLogin)
{
NavigationManager.NavigateTo("/dashboard");
}
else
{
NavigationManager.NavigateTo("/");
}
}

private bool IsValidLogin(string LDAPPath, string domainName, string userName, string password, out string retMessage)
{
bool returnValue = false;
retMessage = null;

try
{
// encode user input before being used in LDAP query.
string safeUserName = EscapeLdapSearchFilter(userName);
var userClaims = HttpContextAccessor.HttpContext?.User?.Claims;
bool isAuthenticated = HttpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false;

string email = HttpContextAccessor.HttpContext?.User?.
FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value;

var de = new DirectoryEntry(LDAPPath, userName, password);

using (var ds = new DirectorySearcher(de) { Filter = "samaccountname=" + safeUserName })
{
SearchResult sr = ds.FindOne();
if (sr == null)
{
retMessage = "Invalid Login.";
}
else
{
string userID = UserInformation.GetByName($"{domainName}\\{userName}", email);

returnValue = true;
}
}
}
catch (Exception ex)
{
retMessage = $"Error during LDAP login: {ex.Message}";
}

return returnValue;
}

private static string EscapeLdapSearchFilter(string searchFilter)
{
StringBuilder escape = new StringBuilder();
for (int i = 0; i < searchFilter.Length; i++)
{
char current = searchFilter;
switch (current)
{
case '\\':
escape.Append(@"\5c");
break;
case '*':
escape.Append(@"\2a");
break;
case '(':
escape.Append(@"\28");
break;
case ')':
escape.Append(@"\29");
break;
case '\u0000':
escape.Append(@"\00");
break;
case '/':
escape.Append(@"\2f");
break;
default:
escape.Append(current);
break;
}
}

return escape.ToString();
}
}

userClaims пусто, isAuthenticated имеет значение false, адрес электронной почты имеет значение null в приведенном ниже коде из файла выше
var userClaims = HttpContextAccessor.HttpContext?.User?.Claims;
bool isAuthenticated = HttpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false;

string email = HttpContextAccessor.HttpContext?.User?.
FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value;

My Program.cs
Я пробовал некоторую конфигурацию аутентификации, но она не сработала, поэтому это прокомментировано.
using Microsoft.AspNetCore.Authentication;
using RCBuisinessLogic.Authentication;
using RCBuisinessLogic.DataAccess;
using RCWebApp.Components;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpContextAccessor();
// Register IConfiguration
builder.Services.AddSingleton(builder.Configuration);

builder.Services.AddSingleton();

// Register AuthenticationConfiguration
builder.Services.AddSingleton();

// Register UserInformation
builder.Services.AddTransient();

// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();

// Add authentication services and configure the custom authentication scheme.
//builder.Services.AddAuthentication(options =>
//{
// options.DefaultAuthenticateScheme = "LDAP";
// options.DefaultChallengeScheme = "LDAP";
//})
//.AddScheme("LDAP", options => { });

// Add authorization services
//builder.Services.AddAuthorization(options =>
//{
// // You can configure authorization policies here if needed.
// options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
//});

var app = builder.Build();

// Use authentication and authorization before handling routing
app.UseAuthentication();
app.UseAuthorization();

//app.Use(async (context, next) =>
//{
// var user = context.User;

// // Only redirect authenticated users if they are NOT trying to access '/userlogin'
// if (user.Identity.IsAuthenticated && !context.Request.Path.StartsWithSegments("/userlogin"))
// {
// // Redirect authenticated users to the dashboard or another page
// context.Response.Redirect("/dashboard");
// return;
// }

// await next(); // Continue the request pipeline
//});

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// 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.UseAntiforgery();

app.MapRazorComponents()
.AddInteractiveServerRenderMode();

app.Run();

Попробовал это промежуточное ПО, предложенное chatgpt, но оно не сработало.

using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using RCBuisinessLogic.Authentication;
using System.DirectoryServices;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;

public class LdapAuthenticationHandler : AuthenticationHandler
{
private readonly UserInformation _userInformation;

public LdapAuthenticationHandler(
IOptionsMonitor options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
UserInformation userInformation)
: base(options, logger, encoder, clock)
{
_userInformation = userInformation;
}

protected override async Task HandleAuthenticateAsync()
{
var username = Context.Request.Form["username"];
var password = Context.Request.Form["password"];
string domain = "mycorp.com"; // Adjust to your LDAP domain

// Perform LDAP authentication here.
var isAuthenticated = AuthenticateWithLdap(username, password, domain, out var userId);
if (isAuthenticated)
{
// Create claims and set the principal
var claims = new List
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.NameIdentifier, userId),
new Claim(ClaimTypes.Email, userId) // Adjust according to your LDAP setup
};

var claimsIdentity = new ClaimsIdentity(claims, "LDAP");
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);

var ticket = new AuthenticationTicket(claimsPrincipal, "LDAP");
return AuthenticateResult.Success(ticket);
}

return AuthenticateResult.Fail("Invalid username or password.");
}

private bool AuthenticateWithLdap(string username, string password, string domain, out string userId)
{
userId = null;

try
{
var ldapPath = $"LDAP://{domain}";
using var de = new DirectoryEntry(ldapPath, username, password);
using var ds = new DirectorySearcher(de)
{
Filter = $"(sAMAccountName={username})"
};

var result = ds.FindOne();
if (result != null)
{
userId = result.Properties["sAMAccountName"][0].ToString(); // Or other user identifier
return true;
}
}
catch
{
// Log error or handle it
}

return false;
}
}


Подробнее здесь: https://stackoverflow.com/questions/792 ... erver-side
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Как интегрировать LDAP с веб-приложением Blazor на базе .NET 8 (серверная сторона)?
    Anonymous » » в форуме C#
    0 Ответы
    26 Просмотры
    Последнее сообщение Anonymous
  • PHP в HTML <СТОРОНА СЕРВЕРА, НЕ СТОРОНА БРАУЗЕРА>
    Anonymous » » в форуме Php
    0 Ответы
    30 Просмотры
    Последнее сообщение Anonymous
  • В чем разница между веб-приложением ASP.NET Core (MVC) и веб-приложением ASP.NET (.NET framework) [дубликат]
    Anonymous » » в форуме C#
    0 Ответы
    50 Просмотры
    Последнее сообщение Anonymous
  • DataTable (серверная сторона) Ajax с использованием CodeIgniter4. Ошибка DataTable не отображается.
    Гость » » в форуме Php
    0 Ответы
    138 Просмотры
    Последнее сообщение Гость
  • Блазор -серверная сторона Windows Impersonation для обновления Active Directory Fake
    Anonymous » » в форуме C#
    0 Ответы
    2 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»