Ontwikkel een C# applicatie met veilige authenticatie en autorisatie
description
Met deze prompt kun je een veilige C# applicatie ontwikkelen die voldoet aan moderne beveiligingsnormen. Het helpt je inzicht te krijgen in gebruikersbeheer, het beschermen van wachtwoorden en het toepassen van toegangscontrole, wat je applicatie beter beschermt tegen ongeautoriseerde toegang en misbruik.
prompt
Help me een C# applicatie te ontwerpen en te implementeren die veilige authenticatie en autorisatie ondersteunt. Beschrijf hoe ik gebruikersbeheer, wac ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een overzicht en voorbeeldcode voor een C#-applicatie die veilige authenticatie en autorisatie ondersteunt, inclusief gebruikersbeheer, wachtwoordbeveiliging en rolgebaseerde toegangscontrole.
**1. Gebruikersbeheer en opslag**
Gebruik een veilige opslag voor gebruikersgegevens, bijvoorbeeld een database of een beveiligde JSON/XML-bestand. Voor eenvoud gebruiken we hier een in-memory lijst, maar in productie moet je een database gebruiken.
**2. Wachtwoordbeveiliging**
Gebruik hashing met salt. In .NET kun je `PasswordHasher` of `Rfc2898DeriveBytes` gebruiken.
**3. Rollen en autorisatie**
Ken rollen toe aan gebruikers en controleer deze bij toegang tot functionaliteiten.
---
### Stap 1: Gebruikersklasse
```csharp
public class Gebruiker
{
public string Gebruikersnaam { get; set; }
public string HashedWachtwoord { get; set; }
public string Salt { get; set; }
public string Rol { get; set; }
}
```
### Stap 2: Wachtwoord hash en verificatie
```csharp
using System.Security.Cryptography;
using System.Text;
public static class Beveiliging
{
public static (string hash, string salt) HashWachtwoord(string wachtwoord)
{
byte[] saltBytes = new byte[16];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(saltBytes);
}
string salt = Convert.ToBase64String(saltBytes);
var pbkdf2 = new Rfc2898DeriveBytes(wachtwoord, saltBytes, 10000);
byte[] hashBytes = pbkdf2.GetBytes(20);
string hash = Convert.ToBase64String(hashBytes);
return (hash, salt);
}
public static bool VerifieerWachtwoord(string wachtwoord, string opgeslagenHash, string opgeslagenSalt)
{
byte[] saltBytes = Convert.FromBase64String(opgeslagenSalt);
var pbkdf2 = new Rfc2898DeriveBytes(wachtwoord, saltBytes, 10000);
byte[] hashBytes = pbkdf2.GetBytes(20);
string hash = Convert.ToBase64String(hashBytes);
return hash == opgeslagenHash;
}
}
```
### Stap 3: Gebruikersregistratie
```csharp
List<Gebruiker> gebruikers = new List<Gebruiker>();
public void RegistreerGebruiker(string gebruikersnaam, string wachtwoord, string rol)
{
var (hash, salt) = Beveiliging.HashWachtwoord(wachtwoord);
gebruikers.Add(new Gebruiker
{
Gebruikersnaam = gebruikersnaam,
HashedWachtwoord = hash,
Salt = salt,
Rol = rol
});
}
```
### Stap 4: Authenticatie
```csharp
public Gebruiker Inloggen(string gebruikersnaam, string wachtwoord)
{
var gebruiker = gebruikers.FirstOrDefault(g => g.Gebruikersnaam == gebruikersnaam);
if (gebruiker != null)
{
if (Beveiliging.VerifieerWachtwoord(wachtwoord, gebruiker.HashedWachtwoord, gebruiker.Salt))
{
return gebruiker; // Ingelogd
}
}
return null; // Onjuiste gegevens
}
```
### Stap 5: Rolgebaseerde autorisatie
```csharp
public bool MagToegang(Gebruiker gebruiker, string vereisteRol)
{
return gebruiker != null && gebruiker.Rol == vereisteRol;
}
```
### Voorbeeldgebruik
```csharp
// Registreren van gebruikers
RegistreerGebruiker("admin1", "wachtwoord123", "admin");
RegistreerGebruiker("gebruiker1", "gebruikerWachtwoord", "gebruiker");
// Inloggen
var ingelogdeGebruiker = Inloggen("admin1", "wachtwoord123");
if (ingelogdeGebruiker != null)
{
Console.WriteLine("Ingelogd als: " + ingelogdeGebruiker.Gebruikersnaam);
if (MagToegang(ingelogdeGebruiker, "admin"))
{
Console.WriteLine("Toegang tot admin-sectie verleend.");
}
else
{
Console.WriteLine("Toegang geweigerd voor deze rol.");
}
}
else
{
Console.WriteLine("Ongeldige inloggegevens.");
}
```
---
### Samenvatting
- Gebruikersgegevens worden opgeslagen inclusief gehashte wachtwoorden en salt.
- Wachtwoorden worden veilig gehasht met PBKDF2.
- Inloggen verifieert wachtwoord en identificeert gebruikers.
- Rollen worden gebruikt voor autorisatie.
- Voor productie: gebruik een veilige database, beveilig je data en implementeer extra beveiliging zoals multi-factor authenticatie.
Heeft u nog verdere vragen of hulp bij specifieke onderdelen?
provider: deepseek
model: deepseek-chat
Ik help je graag met het ontwerpen van een veilige authenticatie- en autorisatie-applicatie in C#. Hier is een complete implementatie:
## 1. Gebruikersmodel en Database Context
```csharp
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
public class Gebruiker
{
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string Gebruikersnaam { get; set; }
[Required]
public byte[] WachtwoordHash { get; set; }
[Required]
public byte[] WachtwoordSalt { get; set; }
[Required]
public string Rol { get; set; }
public DateTime AangemaaktOp { get; set; }
public DateTime LaatstAangemeld { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Gebruiker> Gebruikers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Je_Connection_String_Hier");
}
}
```
## 2. Wachtwoord Beveiligingsservice
```csharp
using System.Security.Cryptography;
using System.Text;
public class WachtwoordService
{
public static void MaakWachtwoordHash(string wachtwoord, out byte[] wachtwoordHash, out byte[] wachtwoordSalt)
{
using (var hmac = new HMACSHA512())
{
wachtwoordSalt = hmac.Key;
wachtwoordHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(wachtwoord));
}
}
public static bool VerifieerWachtwoordHash(string wachtwoord, byte[] opgeslagenHash, byte[] opgeslagenSalt)
{
using (var hmac = new HMACSHA512(opgeslagenSalt))
{
var computedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(wachtwoord));
for (int i = 0; i < computedHash.Length; i++)
{
if (computedHash[i] != opgeslagenHash[i])
return false;
}
}
return true;
}
}
```
## 3. Authenticatie Service
```csharp
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
public class AuthenticatieService
{
private readonly string _jwtSecret;
private readonly AppDbContext _context;
public AuthenticatieService(string jwtSecret, AppDbContext context)
{
_jwtSecret = jwtSecret;
_context = context;
}
public string GenereerJwtToken(Gebruiker gebruiker)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSecret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.NameIdentifier, gebruiker.Id.ToString()),
new Claim(ClaimTypes.Name, gebruiker.Gebruikersnaam),
new Claim(ClaimTypes.Role, gebruiker.Rol)
}),
Expires = DateTime.UtcNow.AddHours(2),
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
public async Task<Gebruiker> Authenticeer(string gebruikersnaam, string wachtwoord)
{
var gebruiker = await _context.Gebruikers
.FirstOrDefaultAsync(u => u.Gebruikersnaam == gebruikersnaam);
if (gebruiker == null || !WachtwoordService.VerifieerWachtwoordHash(
wachtwoord, gebruiker.WachtwoordHash, gebruiker.WachtwoordSalt))
{
return null;
}
gebruiker.LaatstAangemeld = DateTime.UtcNow;
await _context.SaveChangesAsync();
return gebruiker;
}
}
```
## 4. Gebruikersbeheer Service
```csharp
public class GebruikersBeheerService
{
private readonly AppDbContext _context;
public GebruikersBeheerService(AppDbContext context)
{
_context = context;
}
public async Task<Gebruiker> RegistreerGebruiker(string gebruikersnaam, string wachtwoord, string rol = "Gebruiker")
{
if (await _context.Gebruikers.AnyAsync(u => u.Gebruikersnaam == gebruikersnaam))
throw new Exception("Gebruikersnaam bestaat al");
WachtwoordService.MaakWachtwoordHash(wachtwoord, out byte[] wachtwoordHash, out byte[] wachtwoordSalt);
var gebruiker = new Gebruiker
{
Gebruikersnaam = gebruikersnaam,
WachtwoordHash = wachtwoordHash,
WachtwoordSalt = wachtwoordSalt,
Rol = rol,
AangemaaktOp = DateTime.UtcNow,
LaatstAangemeld = DateTime.UtcNow
};
_context.Gebruikers.Add(gebruiker);
await _context.SaveChangesAsync();
return gebruiker;
}
public async Task<bool> VeranderWachtwoord(int gebruikerId, string huidigWachtwoord, string nieuwWachtwoord)
{
var gebruiker = await _context.Gebruikers.FindAsync(gebruikerId);
if (gebruiker == null || !WachtwoordService.VerifieerWachtwoordHash(
huidigWachtwoord, gebruiker.WachtwoordHash, gebruiker.WachtwoordSalt))
{
return false;
}
WachtwoordService.MaakWachtwoordHash(nieuwWachtwoord, out byte[] nieuweHash, out byte[] nieuwSalt);
gebruiker.WachtwoordHash = nieuweHash;
gebruiker.WachtwoordSalt = nieuwSalt;
await _context.SaveChangesAsync();
return true;
}
}
```
## 5. API Controllers
```csharp
[ApiController]
[Route("api/[controller]")]
public class AuthenticatieController : ControllerBase
{
private readonly AuthenticatieService _authService;
private readonly GebruikersBeheerService _gebruikerService;
public AuthenticatieController(AuthenticatieService authService, GebruikersBeheerService gebruikerService)
{
_authService = authService;
_gebruikerService = gebruikerService;
}
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
try
{
var gebruiker = await _authService.Authenticeer(model.Gebruikersnaam, model.Wachtwoord);
if (gebruiker == null)
return Unauthorized("Ongeldige inloggegevens");
var token = _authService.GenereerJwtToken(gebruiker);
return Ok(new
{
Token = token,
Gebruikersnaam = gebruiker.Gebruikersnaam,
Rol = gebruiker.Rol
});
}
catch (Exception ex)
{
return StatusCode(500, "Interne serverfout");
}
}
[HttpPost("registreer")]
public async Task<IActionResult> Registreer([FromBody] RegistreerModel model)
{
try
{
var gebruiker = await _gebruikerService.RegistreerGebruiker(
model.Gebruikersnaam, model.Wachtwoord, model.Rol);
var token = _authService.GenereerJwtToken(gebruiker);
return Ok(new
{
Token = token,
Gebruikersnaam = gebruiker.Gebruikersnaam,
Rol = gebruiker.Rol
});
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
}
public class LoginModel
{
public string Gebruikersnaam { get; set; }
public string Wachtwoord { get; set; }
}
public class RegistreerModel
{
public string Gebruikersnaam { get; set; }
public string Wachtwoord { get; set; }
public string Rol { get; set; } = "Gebruiker";
}
```
## 6. Rolgebaseerde Authorizatie
```csharp
[ApiController]
[Route("api/admin")]
[Authorize(Roles = "Admin")]
public class AdminController : ControllerBase
{
[HttpGet("gebruikers")]
public async Task<IActionResult> GetAllGebruikers([FromServices] AppDbContext context)
{
var gebruikers = await context.Gebruikers
.Select(u => new { u.Id, u.Gebruikersnaam, u.Rol, u.AangemaaktOp })
.ToListAsync();
return Ok(gebruikers);
}
[HttpPost("wijzig-rol/{gebruikerId}")]
public async Task<IActionResult> WijzigRol(int gebruikerId, [FromBody] string nieuweRol)
{
// Implementatie om rol te wijzigen
return Ok();
}
}
[ApiController]
[Route("api/profiel")]
[Authorize]
public class ProfielController : ControllerBase
{
[HttpGet]
public IActionResult GetProfiel()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var gebruikersnaam = User.FindFirst(ClaimTypes.Name)?.Value;
var rol = User.FindFirst(ClaimTypes.Role)?.Value;
return Ok(new { userId, gebruikersnaam, rol });
}
}
```
## 7. Program.cs Configuratie
```csharp
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Services toevoegen
builder.Services.AddDbContext<AppDbContext>();
builder.Services.AddScoped<AuthenticatieService>();
builder.Services.AddScoped<GebruikersBeheerService>();
// JWT Authentication
var jwtSecret = builder.Configuration["Jwt:Secret"];
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSecret)),
ValidateIssuer = false,
ValidateAudience = false
};
});
builder.Services.AddAuthorization();
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
```
## 8. appsettings.json
```json
{
"Jwt": {
"Secret": "Jouw_Veilige_Geheime_Sleutel_Minimaal_256_Bits"
},
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=AuthDB;Trusted_Connection=true;"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
```
## Belangrijke beveiligingsoverwegingen:
1. **Wachtwoordhashing**: Gebruik altijd salted hashes (HMACSHA512)
2. **JWT Tokens**: Beperk de geldigheidsduur (2 uur in dit voorbeeld)
3. **HTTPS**: Gebruik altijd HTTPS in productie
4. **Rate Limiting**: Implementeer rate limiting voor login pogingen
5. **Input Validatie**: Valideer alle gebruikersinput
6. **Error Handling**: Geef geen specifieke foutmeldingen bij authenticatiefouten
Dit is een basisimplementatie. Voor productiegebruik overweeg:
- Refresh tokens implementeren
- Two-factor authenticatie toevoegen
- Audit logging
- Beveiligingsheaders configureren
- Dependency Injection optimaliseren