C# | Вопросы собесов
5.1K subscribers
34 photos
1 file
980 links
Download Telegram
🤔 Что такое паттерн Event Sourcing?

Паттерн Event Sourcing (событийное моделирование) — это подход к управлению состоянием приложения, при котором все изменения состояния представляются в виде последовательности событий. Вместо хранения текущего состояния объекта в базе данных, сохраняются все изменения состояния (события), которые произошли с этим объектом. Текущее состояние может быть восстановлено путем последовательного применения этих событий.

🚩Основные концепции Event Sourcing:

🟠События (Events): События представляют собой неизменяемые записи фактов, которые произошли в системе. Каждое событие описывает изменение состояния.
🟠Источники событий (Event Stores): Специальные хранилища, которые сохраняют последовательности событий. Они обеспечивают устойчивость событий и возможность их повторного воспроизведения.
🟠Агрегаты (Aggregates): Логические группы объектов, которые обрабатывают команды и генерируют события.
🟠Команды (Commands): Запросы на выполнение изменений, которые обрабатываются агрегатами и приводят к генерации событий.
🟠Проекционные модели (Projections): Модели, создаваемые из последовательностей событий для представления данных в удобной для чтения форме.

🚩Преимущества Event Sourcing:

🟠Историчность: Все изменения состояния хранятся в виде событий, что позволяет восстановить любое прошлое состояние системы.
🟠Отладка и аудит: Полная история изменений облегчает отладку и проведение аудита.
🟠Производительность: Проекции позволяют оптимизировать запросы к данным.
🟠Гибкость: Возможность пересоздания проекций с новыми требованиями без изменения основного хранилища событий.

🚩Недостатки Event Sourcing:

🟠Сложность: Реализация Event Sourcing требует дополнительных усилий и знаний.
🟠Объем данных: Хранение всех событий может занимать много места.

public class AccountCreated
{
public Guid AccountId { get; }
public string Owner { get; }

public AccountCreated(Guid accountId, string owner)
{
AccountId = accountId;
Owner = owner;
}
}

public class MoneyDeposited
{
public Guid AccountId { get; }
public decimal Amount { get; }

public MoneyDeposited(Guid accountId, decimal amount)
{
AccountId = accountId;
Amount = amount;
}
}

public class MoneyWithdrawn
{
public Guid AccountId { get; }
public decimal Amount { get; }

public MoneyWithdrawn(Guid accountId, decimal amount)
{
AccountId = accountId;
Amount = amount;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
🤔 Что такое паттерн CQRS?

🚩Что такое паттерн CQRS — паттерн, разделяющий операции чтения и записи данных.

Основные концепции
🟠Команды (Commands): Операции записи, изменяющие состояние системы.
🟠Запросы (Queries): Операции чтения, не изменяющие состояние системы.

Преимущества
🟠Оптимизация производительности: Раздельные модели для чтения и записи могут быть оптимизированы отдельно.
🟠Упрощение кода: Разделение логики упрощает код и его поддержку.
🟠Масштабируемость: Легче масштабировать чтение и запись независимо.

Недостатки
🟠Сложность: Увеличение сложности системы.
🟠Синхронизация данных: Требуется механизм синхронизации между моделями чтения и записи.

Команда (Command)
public class CreateUserCommand
{
public string Name { get; }
public CreateUserCommand(string name)
{
Name = name;
}
}


Обработчик команды (Command Handler)
public class CreateUserCommandHandler
{
private readonly UserDbContext _context;

public CreateUserCommandHandler(UserDbContext context)
{
_context = context;
}

public void Handle(CreateUserCommand command)
{
var user = new User { Name = command.Name };
_context.Users.Add(user);
_context.SaveChanges();
}
}


Запрос (Query)
public class GetUserQuery
{
public int UserId { get; }
public GetUserQuery(int userId)
{
UserId = userId;
}
}


Обработчик запроса (Query Handler)
public class GetUserQueryHandler
{
private readonly UserDbContext _context;

public GetUserQueryHandler(UserDbContext context)
{
_context = context;
}

public User Handle(GetUserQuery query)
{
return _context.Users.Find(query.UserId);
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍141
🤔 Какой модификатор доступа делает член класса доступным только в пределах своего класса и подклассов?
Anonymous Quiz
27%
private
62%
protected
10%
internal
1%
public
🔥8😁2
🤔 Что такое микросервис?

🚩Что такое микросервис

Микросервис — это архитектурный стиль, который предполагает создание приложения в виде набора небольших, автономных сервисов, каждый из которых отвечает за выполнение конкретной бизнес-функции. Эти сервисы могут разрабатываться, развёртываться и масштабироваться независимо друг от друга.

🚩Основные характеристики микросервисов

🟠Автономность: Каждый микросервис работает независимо и может быть развёрнут отдельно.
🟠Малый размер: Микросервисы обычно небольшие и выполняют одну конкретную задачу.
🟠Чёткие границы: Микросервисы имеют чётко определённые границы и взаимодействуют друг с другом через хорошо определённые API.
🟠Независимость развертывания: Микросервисы можно развёртывать и обновлять независимо друг от друга.
🟠Разнообразие технологий: В каждом микросервисе можно использовать разные технологии, языки программирования и базы данных в зависимости от задачи.

Преимущества микросервисов
🟠Масштабируемость: Легко масштабировать отдельные микросервисы по мере необходимости.
🟠Упрощенная разработка и развёртывание: Меньшие команды могут работать над отдельными микросервисами, что ускоряет разработку.
🟠Независимые обновления: Можно обновлять и развёртывать микросервисы без остановки всего приложения.
🟠Устойчивость к сбоям: Сбой в одном микросервисе не приводит к сбою всего приложения.

Недостатки микросервисов
🟠Сложность управления: Требуется сложная инфраструктура для управления множеством микросервисов.
🟠Сложность коммуникаций: Требуется надежный механизм взаимодействия между микросервисами.
🟠Трудности в тестировании: Тестирование микросервисной архитектуры может быть сложнее по сравнению с монолитной.
🟠Управление данными: Могут возникнуть сложности с согласованностью данных и транзакциями.

🚩Рассмотрим пример интернет-магазина, разбитого на несколько микросервисов:

🟠User Service: Управляет пользователями и их учетными записями.
🟠Product Service: Управляет информацией о продуктах.
🟠Order Service: Обрабатывает заказы.
🟠Payment Service: Управляет платежами.

Каждый из этих микросервисов имеет своё собственное API и базу данных.
// Пример простого контроллера для микросервиса пользователя
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
private readonly IUserService _userService;

public UserController(IUserService userService)
{
_userService = userService;
}

[HttpGet("{id}")]
public ActionResult<User> GetUser(int id)
{
var user = _userService.GetUserById(id);
if (user == null)
{
return NotFound();
}
return Ok(user);
}

[HttpPost]
public ActionResult<User> CreateUser([FromBody] User user)
{
var createdUser = _userService.CreateUser(user);
return CreatedAtAction(nameof(GetUser), new { id = createdUser.Id }, createdUser);
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20
🤔 Какие есть положительные и отрицательные моменты у микросервиса?

🚩Положительные моменты микросервисов

🟠Масштабируемость
Легко масштабировать только те части системы, которые требуют этого, без необходимости масштабировать всё приложение. Например, если у вас есть микросервис, обрабатывающий заказы, и он испытывает высокую нагрузку, вы можете масштабировать только его, не трогая другие части системы.

🟠Независимость развертывания
Микросервисы можно развёртывать, обновлять и откатывать независимо друг от друга. Например вы можете обновить микросервис аутентификации без остановки микросервиса каталога продуктов.

🟠Устойчивость к сбоям
Отказ одного микросервиса не приводит к отказу всего приложения. Например, если микросервис обработки платежей выходит из строя, пользователи всё равно могут просматривать продукты и добавлять их в корзину.

🟠Гибкость технологий
Каждый микросервис может быть написан на своем языке программирования и использовать свои технологии, что позволяет выбирать наиболее подходящие инструменты для каждой задачи. Например, Вы можете использовать Python для микросервиса машинного обучения и .NET для микросервиса управления пользователями.

🟠Ускоренная разработка:
Малые команды могут работать над разными микросервисами параллельно, что ускоряет процесс разработки. Например, одна команда может работать над микросервисом управления пользователями, в то время как другая команда работает над микросервисом заказа.

🚩Отрицательные моменты микросервисов

🟠Сложность управления
Управление множеством микросервисов требует сложной инфраструктуры для оркестрации, мониторинга и логирования. Например, вам нужно внедрить систему оркестрации, такую как Kubernetes, чтобы управлять развертыванием и масштабированием микросервисов.

🟠 Сложность коммуникаций
Необходимо наладить надежные межсервисные коммуникации, что может быть сложно и привести к повышенным накладным расходам. Например, вам нужно решить, использовать ли синхронные (HTTP/REST) или асинхронные (сообщения, очереди) методы связи между микросервисами.

🟠Трудности в тестировании
Тестирование микросервисной архитектуры сложнее из-за необходимости интеграции и взаимодействия между множеством независимых компонентов. Например вам нужно создать среду для интеграционного тестирования, которая включает все необходимые микросервисы.

🟠Управление данными
Согласованность данных и управление транзакциями становятся более сложными задачами в распределённой системе. Например, вам нужно внедрить сложные механизмы для обеспечения согласованности данных, такие как саги или распределённые транзакции.

🟠Затраты на инфраструктуру: Разделение на множество микросервисов может увеличить затраты на инфраструктуру, особенно если требуется множество ресурсов для управления этими микросервисами. Например, Вам может понадобиться больше серверов и инструментов для управления и мониторинга микросервисов.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
🤯16🤔1👾1
🤔 Как бы паттерн использовал для паттерна разделяй и властвуй?

🚩Что такое "Разделяй и властвуй"

Паттерн "Разделяй и властвуй" (Divide and Conquer) разделяет задачи на более мелкие подзадачи для упрощения кода и повышения эффективности.

🚩Примеры

🟠Микросервисы: Разделяют приложение на независимые сервисы, которые можно развёртывать и масштабировать отдельно. Например, Микросервисы для пользователей, продуктов, заказов и платежей.
🟠Компонентная архитектура: Делит систему на независимые компонент. Например, Веб-страница с отдельными компонентами для заголовка, контента и футера.

🚩Преимущества

🟠Упрощение кода: Легче понимать и поддерживать.
🟠Масштабируемость: Легче масштабировать отдельные части.
🟠Независимость разработки: Различные команды могут работать параллельно.

🚩Недостатки

🟠Сложность координации: Требует управления взаимодействием между частями.
🟠Интеграционные накладные расходы: Требует дополнительных усилий для интеграции.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🤯2
🤔 Какой код корректно использует оператор ?.?
Anonymous Quiz
50%
var name = obj?.ToString();
10%
var name = obj?.Name();
32%
var name = obj?.Name;
7%
var name = obj?.GetName;
🤔9👍2👀1
🤔 Какие есть новые полезные функции в C#?

🚩C# 9.0

Records:
Предназначены для создания неизменяемых типов данных с минимальным шаблонным кодом
public record Person(string FirstName, string LastName);


Init-only Properties:
Позволяют устанавливать значения свойств только при инициализации объекта.
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}


With-expressions:
Используются для создания копий неизменяемых объектов с изменёнными значениями.
var person1 = new Person("John", "Doe");
var person2 = person1 with { LastName = "Smith" };


Top-level Statements:
Позволяют писать код без явного класса или метода Main.
using System;
Console.WriteLine("Hello, World!");


Pattern Matching Enhancements
:
Улучшения в сопоставлении с образцом, включая логические шаблоны (and, or, not) и шаблоны типа is.
if (person is Person { FirstName: "John", LastName: "Doe" })
{
Console.WriteLine("It's John Doe!");
}


🚩C# 10.0

Global using directives:
Позволяют объявлять using директивы, применимые ко всему проекту.
// В globalusing.cs
global using System;
global using System.Collections.Generic;


File-scoped Namespace:
Упрощённый синтаксис для объявления пространства имён для всего файла.
namespace MyNamespace;
class MyClass { }


Record Structs:
Записи, которые могут быть значимыми типами.
public record struct Point(int X, int Y); 


Improved `lambda` expressions:
Улучшения в синтаксисе и типизации лямбда-выражений.
Func<int, int> square = x => x * x;     


🚩C# 11.0

Required Members:
Обязательные члены, которые должны быть установлены при создании объекта.
public class Person
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
}


Raw String Literals:
Упрощённый синтаксис для создания многострочных строковых литералов без экранирования.
var json = """
{
"name": "John Doe",
"age": 30
}
""";


Generic Attributes:
Позволяют создавать атрибуты с обобщёнными параметрами.
[AttributeUsage(AttributeTargets.Class)]
public class MyGenericAttribute<T> : Attribute { }

[MyGenericAttribute<int>]
public class MyClass { }


List Pattern Matching:
Сопоставление с образцом для списков.
if (numbers is [1, 2, .., 10])
{
Console.WriteLine("The list starts with 1, 2 and ends with 10.");
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍312
🤔 Какие есть методы оптимизации LINQ запросов?

Для оптимизации LINQ запросов в C# используйте компилируемые запросы, минимизируйте запросы в циклах, выбирайте только нужные поля, применяйте отложенное выполнение и метод .AsNoTracking() для чтения данных.

🟠Отложенное выполнение (Deferred Execution)
LINQ-запросы не выполняются до тех пор, пока не начнётся итерация по ним. Это позволяет объединить несколько операций в один запрос к базе данных.
var query = dbContext.Users.Where(u => u.IsActive); // Запрос ещё не выполнен
var activeUsers = query.ToList(); // Запрос выполнен здесь


🟠Использование `ToList` и `ToArray` только при необходимости
Избегайте ненужных вызовов ToList и ToArray, так как они приводят к немедленному выполнению запроса и загрузке всех данных в память.
var users = dbContext.Users.Where(u => u.IsActive).ToList(); // Не вызывайте ToList() до тех пор, пока не нужно


🟠Проекционная выборка (`Select`)
Выбирайте только необходимые поля, чтобы уменьшить объем данных, передаваемых по сети и загружаемых в память.
var userNames = dbContext.Users
.Where(u => u.IsActive)
.Select(u => new { u.FirstName, u.LastName })
.ToList();


🟠Фильтрация на уровне базы данных (`Where`)
Фильтруйте данные на уровне базы данных, а не в памяти, чтобы уменьшить количество передаваемых данных.
var activeUsers = dbContext.Users.Where(u => u.IsActive).ToList(); // Фильтрация на уровне базы данных


🟠Пагинация (`Skip` и `Take`)
Используйте пагинацию для работы с большими наборами данных, чтобы загружать и обрабатывать только нужные страницы.
var pageNumber = 2;
var pageSize = 10;
var paginatedUsers = dbContext.Users
.Where(u => u.IsActive)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();


🟠Избегайте сложных выражений в циклах
Сложные LINQ-запросы в циклах могут привести к многочисленным запросам к базе данных. Постарайтесь минимизировать их или объединить в один запрос.
// Плохо
foreach (var userId in userIds)
{
var user = dbContext.Users.FirstOrDefault(u => u.Id == userId);
}

// Хорошо
var users = dbContext.Users.Where(u => userIds.Contains(u.Id)).ToList();


🟠Использование асинхронных методов
Асинхронные методы, такие как ToListAsync, FirstOrDefaultAsync и SingleOrDefaultAsync, помогают избежать блокировки потоков и улучшить производительность.
var activeUsers = await dbContext.Users.Where(u => u.IsActive).ToListAsync();


🟠Компилированные запросы
Для часто выполняемых запросов используйте EF.CompileQuery в Entity Framework, чтобы уменьшить накладные расходы на компиляцию запросов.
private static readonly Func<MyDbContext, bool, IQueryable<User>> GetActiveUsersQuery =
EF.CompileQuery((MyDbContext context, bool isActive) =>
context.Users.Where(u => u.IsActive == isActive));

var activeUsers = GetActiveUsersQuery(dbContext, true).ToList();


🟠Анализ генерируемого SQL
Используйте инструменты профилирования и логирования для анализа генерируемых SQL-запросов, чтобы найти потенциальные узкие места и неэффективные запросы.
var sql = dbContext.Users.Where(u => u.IsActive).ToQueryString();
Console.WriteLine(sql);


🟠Правильное использование индексов
Убедитесь, что индексы в базе данных настроены правильно для часто выполняемых запросов, чтобы улучшить производительность поиска.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25
🤔 Как реализовать обработку исключений

Обработка исключений в C# необходима для правильного управления ошибками, возникающими во время выполнения программы. Она позволяет перехватывать ошибки и выполнять соответствующие действия, чтобы программа не завершалась аварийно. Рассмотрим основные конструкции для обработки исключений: try, catch, finally, и throw.

🟠Конструкция try-catch
Конструкция try-catch используется для перехвата и обработки исключений. Код, который может вызвать исключение, помещается в блок try, а код для обработки исключения - в блок catch.
try
{
// Код, который может вызвать исключение
int result = 10 / 0;
}
catch (DivideByZeroException ex)
{
// Обработка исключения
Console.WriteLine("Произошло деление на ноль: " + ex.Message);
}
catch (Exception ex)
{
// Обработка других исключений
Console.WriteLine("Произошла ошибка: " + ex.Message);
}


🟠Конструкция finally
Блок finally выполняется в любом случае после завершения блоков try и catch, независимо от того, возникло исключение или нет. Он часто используется для освобождения ресурсов, таких как файловые дескрипторы или сетевые подключения.
try
{
// Код, который может вызвать исключение
using (StreamReader sr = new StreamReader("file.txt"))
{
// Чтение файла
}
}
catch (FileNotFoundException ex)
{
// Обработка исключения
Console.WriteLine("Файл не найден: " + ex.Message);
}
finally
{
// Очистка ресурсов
Console.WriteLine("Закрытие файла.");
}


🟠Генерация исключений с помощью throw
Ключевое слово throw используется для генерации исключений. Оно может быть использовано как для передачи возникшего исключения дальше по цепочке вызовов, так и для создания нового исключения.
void ProcessNumber(int number)
{
if (number < 0)
{
throw new ArgumentOutOfRangeException("number", "Число должно быть неотрицательным");
}

// Продолжение обработки
}


🟠Вложенные и повторные исключения
Вложенные исключения позволяют захватывать одно исключение и генерировать новое, сохраняя информацию о первоначальном исключении.
try
{
// Код, который может вызвать исключение
MethodThatThrows();
}
catch (Exception ex)
{
throw new InvalidOperationException("Ошибка в процессе выполнения", ex);
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
🤔 Почему лучше использовать ExceptionX обычный?

Использование специализированных исключений, таких как ArgumentException, InvalidOperationException, или пользовательских исключений (например, MyCustomException), лучше, чем использование общего исключения Exception. Это позволяет более точно и детально управлять ошибками.

🚩Почему это важно:

🟠Уточнение причины ошибки
Специализированные исключения помогают точнее определить, что именно пошло не так. Например, ArgumentNullException ясно указывает, что переданный аргумент был null, в то время как Exception может означать любую ошибку.
void ProcessData(string data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data), "Data cannot be null");
}
// Обработка данных
}


🟠Улучшение читаемости кода
Использование конкретных исключений делает код более читаемым и поддерживаемым. Разработчики, читающие код, сразу понимают, какие именно ошибки могут возникнуть и как с ними справляться.
try
{
// Код, который может вызвать исключение
}
catch (ArgumentNullException ex)
{
// Обработка ситуации, когда аргумент был null
}
catch (InvalidOperationException ex)
{
// Обработка некорректного состояния операции
}


🟠Улучшение отладки
Специализированные исключения предоставляют больше информации для отладки. Это позволяет быстрее найти и исправить ошибки, так как разработчики получают более точные сообщения об ошибках.
try
{
// Код, который может вызвать исключение
}
catch (Exception ex)
{
// Общее исключение, трудно определить причину
Console.WriteLine("Произошла ошибка: " + ex.Message);
}


🟠Гранулированная обработка исключений
С помощью специализированных исключений можно различать разные типы ошибок и применять к ним разные стратегии обработки. Это делает обработку ошибок более гибкой и точной.
try
{
// Код, который может вызвать исключение
}
catch (ArgumentNullException ex)
{
Console.WriteLine("Обязательный аргумент не был передан: " + ex.Message);
// Специфическая обработка для отсутствующего аргумента
}
catch (ArgumentException ex)
{
Console.WriteLine("Аргумент некорректен: " + ex.Message);
// Специфическая обработка для некорректного аргумента
}


🟠Создание пользовательских исключений
В сложных приложениях можно создавать пользовательские исключения, которые более точно описывают уникальные ошибки, специфичные для вашего приложения.
public class MyCustomException : Exception
{
public MyCustomException(string message) : base(message) { }
}

void DoSomething()
{
throw new MyCustomException("Произошла специфическая ошибка.");
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤔1🤯1👾1
🤯21😁4
🤔 Зачем может понадобиться делать свой exception?

Создание своих исключений в C# может понадобиться в ряде случаев, когда стандартные исключения не подходят для описания специфических ошибок, возникающих в вашем приложении.

🟠Специфичность и Контекст
Свои исключения позволяют дать более точное описание ошибки, связанной с конкретной бизнес-логикой или контекстом приложения. Это делает код более понятным и легким для сопровождения.
public class InsufficientFundsException : Exception
{
public InsufficientFundsException(string message) : base(message) { }
}

public class BankAccount
{
public void Withdraw(decimal amount)
{
if (amount > Balance)
{
throw new InsufficientFundsException("Недостаточно средств на счете.");
}
// Логика снятия средств
}
}


🟠Улучшение Отладки и Логирования
Свои исключения могут включать дополнительную информацию, которая поможет лучше понять контекст ошибки при отладке или логировании.
public class DataNotFoundException : Exception
{
public string DataId { get; }

public DataNotFoundException(string dataId, string message) : base(message)
{
DataId = dataId;
}
}

void GetData(string id)
{
// Если данные не найдены
throw new DataNotFoundException(id, "Данные не найдены для ID: " + id);
}


🟠Группировка Исключений
Создание своих исключений позволяет логически группировать ошибки, что облегчает их обработку в коде. Например, можно создать базовое исключение для всех ошибок, связанных с доступом к базе данных, и наследовать от него конкретные типы ошибок.
public class DatabaseException : Exception
{
public DatabaseException(string message) : base(message) { }
}

public class RecordNotFoundException : DatabaseException
{
public RecordNotFoundException(string message) : base(message) { }
}

public class ConnectionFailedException : DatabaseException
{
public ConnectionFailedException(string message) : base(message) { }
}


🟠Соответствие Архитектуре
В сложных системах с многоуровневой архитектурой свои исключения помогают управлять ошибками на каждом уровне, передавая их на более высокий уровень для централизованной обработки.
public class BusinessException : Exception
{
public BusinessException(string message) : base(message) { }
}

public class PaymentProcessingException : BusinessException
{
public PaymentProcessingException(string message) : base(message) { }
}

void ProcessPayment()
{
try
{
// Логика обработки платежа
}
catch (Exception ex)
{
throw new PaymentProcessingException("Ошибка при обработке платежа: " + ex.Message);
}
}


🟠Обеспечение Лучшего Взаимодействия с Пользователем
Пользовательские исключения могут содержать информацию, которая будет полезна для отображения пользователю, улучшая пользовательский опыт.
public class UserNotAuthorizedException : Exception
{
public UserNotAuthorizedException(string message) : base(message) { }
}

void AccessRestrictedArea()
{
if (!userIsAuthorized)
{
throw new UserNotAuthorizedException("Пользователь не имеет права доступа к этому разделу.");
}
// Логика доступа
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9😁1
🤔 Какие принципы и практики используешь для обеспечения безопасности приложений?

🟠Валидация и Санитизация Входных Данных
Валидация входных данных помогает предотвратить атаки, такие как SQL-инъекции, XSS (межсайтовый скриптинг) и другие. SQL-инъекции: Используйте параметризованные запросы или ORM (например, Entity Framework).
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Users WHERE Username = @username", conn))
{
cmd.Parameters.AddWithValue("@username", username);
// Выполнение команды
}


XSS: Используйте библиотеку для экранирования HTML, например, AntiXSS.
string safeContent = Microsoft.Security.Application.Encoder.HtmlEncode(userInput);


🟠Использование Аутентификации и Авторизации
Обеспечьте надежную аутентификацию и разграничение доступа к ресурсам.
Аутентификация: Используйте современные методы аутентификации, такие как OAuth, OpenID Connect.
Авторизация: Применяйте ролевую или заявочную (claims-based) авторизацию.
[Authorize(Roles = "Admin")]
public IActionResult AdminOnly()
{
return View();
}


🟠Защита от CSRF (Межсайтовая подделка запросов)
Используйте анти-CSRF токены для защиты от CSRF атак.
<form asp-action="Create">
<input type="hidden" name="__RequestVerificationToken" value="@Antiforgery.GetTokens(HttpContext).RequestToken" />
<!-- Другие поля формы -->
</form>


🟠Шифрование и Защита Данных
Шифруйте чувствительные данные как при передаче, так и при хранении.
При передаче: Используйте HTTPS для шифрования данных, передаваемых через сеть.
При хранении: Используйте библиотеки для шифрования, такие как System.Security.Cryptography.
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
// Шифрование данных
}


🟠Логирование и Мониторинг
Внедрите логирование и мониторинг для обнаружения и анализа подозрительной активности.
Логирование: Логируйте важные действия, такие как входы в систему, изменения данных.
Мониторинг: Используйте инструменты мониторинга, такие как Application Insights, для отслеживания состояния приложения.
_logger.LogInformation("User {UserId} logged in.", userId);


🟠Управление Ошибками и Исключениями
Не показывайте подробные сообщения об ошибках пользователям, чтобы не раскрывать внутреннюю структуру приложения.
Обработка исключений: Ловите и корректно обрабатывайте исключения, предоставляя пользователю дружелюбные сообщения.
try
{
// Код, который может вызвать исключение
}
catch (Exception ex)
{
_logger.LogError(ex, "Произошла ошибка.");
return View("Error");
}


🟠Обновления и Патчи
Регулярно обновляйте используемые библиотеки и фреймворки, чтобы закрывать уязвимости.

🟠Минимизация Поверхности Атаки
Удалите или отключите ненужные функции и сервисы, чтобы минимизировать возможные точки входа для атак.

🟠Защита Конфигурации
Защитите конфигурационные файлы, содержащие чувствительную информацию.
Секреты и ключи: Используйте секреты и безопасное хранилище для конфиденциальной информации.
var connectionString = Configuration["ConnectionStrings:DefaultConnection"];


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7