Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🟣
Intermediaire 25 min .NET

Securiser une application .NET

Pourquoi Securiser une application .NET ?

La sécurité est un élément fondamental pour tout développement logiciel, mais particulièrement crucial dans les environnements modernes où l'information est partagée et traitée à grande échelle. En tant que développeur senior .NET avec 10+ ans d'expérience, vous devez comprendre que la sécurité ne se limite pas aux aspects graphiques ou fonctionnels de votre application. Elle englobe également des aspects tels que la protection contre les attaques externes, la gestion des données sensibles et la conformité réglementaire.

Un cas concret est le secteur financier, où une application non sécurisée peut entraîner des dommages financiers importants et même des pénalités légales. Dans ce contexte, la sécurité n'est pas un choix optionnel mais une exigence de la part des clients et des régulateurs.

Prerequis

  • Connaissance approfondie du langage C#
  • Compréhension des concepts fondamentaux de l'architecture .NET
  • Familiarité avec les frameworks ASP.NET Core et Entity Framework Core
  • Connaissance des principes de sécurité informatique (cryptage, authentification, autorisation)
  • Installation d'Visual Studio 2019 ou ultérieur avec la charge de travail de développement web

Concepts fondamentaux

Authentification et Autorisation

L'authentification est le processus par lequel un utilisateur prouve son identité. L'autorisation consiste à déterminer les actions que l'utilisateur peut effectuer une fois authentifié.

Schema Mental:

Authentification -> Identification (Utilisateur) -> Authentification (Serveur)
Autorisation -> Permission de l'utilisateur sur la ressource
net
## Authentification avec ASP.NET Core
public async Task<IActionResult> Login(LoginViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = await _userManager.FindByNameAsync(model.Username);
        if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
        {
            await _signInManager.SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home");
        }
        ModelState.AddModelError(string.Empty, "Invalid login attempt.");
    }
    return View(model);
}

Cryptage des données

Le cryptage est un processus qui transforme les données en une forme non lisible pour prévenir les accès non autorisés.

Schema Mental:

Données claires -> Cryptage (algorithme) -> Données chiffrées
Données chiffrées -> Décryptage (meme algorithme) -> Données claires
net
## Cryptage et décryptage de mots de passe avec ASP.NET Core
public string Encrypt(string password)
{
    using (var sha256 = SHA256.Create())
    {
        byte[] bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password));
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < bytes.Length; i++)
        {
            builder.Append(bytes[i].ToString("x2"));
        }
        return builder.ToString();
    }
}

Validation des entrées utilisateur

La validation des entrées utilisateur est cruciale pour prévenir les attaques telles que l'injection SQL et le hacking par déni de service (DoS).

Schema Mental:

Entrée utilisateur -> Validation -> Traitement sécurisé
net
## Validation des entrées utilisateur avec ASP.NET Core
[HttpPost]
public async Task<IActionResult> Create([Bind("Title,Description")] BlogPost blogPost)
{
    if (ModelState.IsValid)
    {
        // Traitement sécurisé de la publication de blog
        _context.Add(blogPost);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(blogPost);
}

Mise en pratique : projet fil rouge

Mini-Projet : Gestionnaire de Tâches

Étape 1 : Création du Projet

  1. Ouvrez Visual Studio.
  2. Créez un nouveau projet ASP.NET Core Web App (Model-View-Controller).
  3. Sélectionnez "ASP.NET Core 6.0" et "Web Application".
  4. Nommez le projet TaskManager et cliquez sur "Create".

Étape 2 : Configuration de la base de données

  1. Installez Entity Framework Core.
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
  1. Créez un modèle de données.
## Models/Task.cs
public class Task
{
    public int Id { get; set; }
    public string Title { get; set; }
    public bool IsCompleted { get; set; }
}
  1. Configurez la base de données.
## Data/ApplicationDbContext.cs
public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options) {}

    public DbSet<Task> Tasks { get; set; }
}
  1. Mettez à jour le fichier appsettings.json.
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TaskManager;Trusted_Connection=True;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}
  1. Ajoutez la configuration de la base de données dans Program.cs.
## Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Étape 3 : Création des contrôleurs et vues

  1. Créez un contrôleur TasksController.
## Controllers/TasksController.cs
public class TasksController : Controller
{
    private readonly ApplicationDbContext _context;

    public TasksController(ApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<IActionResult> Index()
    {
        return View(await _context.Tasks.ToListAsync());
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("Title,IsCompleted")] Task task)
    {
        if (ModelState.IsValid)
        {
            _context.Add(task);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(task);
    }
}
  1. Créez une vue Index.
<!-- Views/Tasks/Index.cshtml -->
@model IEnumerable<TaskManager.Models.Task>

@{
    ViewData["Title"] = "Tasks";
}

<h1>Tasks</h1>

<p>
    <a asp-action="Create">Create New Task</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>Title</th>
            <th>Status</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>@item.Title</td>
            <td>@(item.IsCompleted ? "Completed" : "Pending")</td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

<p>
    <a asp-action="Create">Create New Task</a>
</p>
  1. Créez une vue Create.
<!-- Views/Tasks/Create.cshtml -->
@model TaskManager.Models.Task

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Task</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="IsCompleted" class="control-label"></label>
                <input asp-for="IsCompleted" class="form-check-input" />
                <span asp-validation-for="IsCompleted" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Étape 4 : Exécution de l'application

  1. Lancez l'application.
dotnet run
  1. Naviguez jusqu'à /Tasks pour voir la liste des tâches et créer de nouvelles tâches.

Erreurs frequentes et debugging

Erreur 1 : InvalidOperationException: The model backing 'DbContext' has changed since the database was last read.

## ❌ Mauvais
_context.Tasks.ToList();

## ✅ Correct
await _context.Tasks.ToListAsync();

Erreur 2 : SqlException: There is already an object named 'Task' in the database.

## ❌ Mauvais
public DbSet<Task> Tasks { get; set; }

## ✅ Correct
public DbSet<MyTask> Tasks { get; set; }

Erreur 3 : InvalidOperationException: The ViewData item that has the key 'TaskManager.Models.Task' is of type 'System.Collections.Generic.List1[TaskManager.Models.Task]' but must be of type 'TaskManager.Models.Task'.`

## ❌ Mauvais
@model TaskManager.Models.Task

## ✅ Correct
@model IEnumerable<TaskManager.Models.Task>

Pour aller plus loin

1. Authentification avec JWT (JSON Web Tokens)

L'utilisation de JWT permet une authentification sécurisée sans utiliser des cookies.

Lien vers la documentation officielle

2. Sécurité des APIs RESTful

La sécurisation des APIs est cruciale pour prévenir l'accès non autorisé.

Lien vers la documentation officielle

3. Protection contre les injections SQL

La protection contre les injections SQL est essentielle pour prévenir les attaques SQL injection.

Lien vers la documentation officielle

Défi pratique : Ajouter une fonctionnalité de sécurité

Ajoutez une fonctionnalité de protection contre les injections SQL à un projet existant et expliquez comment elle fonctionne.


Ce tutoriel couvre les principaux aspects de la sécurité d'une application .NET, en fournissant des exemples pratiques et des détails techniques. En suivant ce guide, vous serez mieux préparé pour gérer la sécurité dans vos projets .NET futurs.

Besoin d'aide sur .NET ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Comment configurer la sécurité des connexions avec une base de données SQL Server dans une application .NET?
Pour sécuriser les connexions à une base de données SQL Server, utilisez des chaînes de connexion sécurisées (connection strings) qui incluent l'utilisation d'identifiants et de mots de passe. Assurez-vous que le trafic entre votre application .NET et la base de données est chiffré en utilisant SSL/TLS.
Quelles sont les meilleures pratiques pour gérer les secrets et les clés sensibles dans une application .NET?
Pour gérer les secrets et les clés sensibles, utilisez le gestionnaire de secret local (.NET Secret Manager) ou un service de stockage sécurisé comme Azure Key Vault. Évitez d'hardcoder des informations sensibles directement dans le code source.
Comment protéger contre l'injection SQL dans une application .NET?
Pour prévenir les injections SQL, utilisez toujours des paramètres de commande lors de la construction des requêtes SQL. Évitez d'utiliser des chaînes de caractères directement intégrées à vos requêtes SQL pour éviter toute manipulation malveillante.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.