dotnet-security
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese.NET Security - Quick Reference
.NET安全 - 快速参考
When NOT to Use This Skill
何时不使用本技能
- General OWASP concepts - Use or
owaspskillowasp-top-10 - Java security - Use skill
java-security - Python security - Use skill
python-security - Secrets management - Use skill
secrets-management
Deep Knowledge: Usewith technology:mcp__documentation__fetch_docsfor ASP.NET Core security documentation.dotnet
- 通用OWASP概念 - 使用或
owasp技能owasp-top-10 - Java安全 - 使用技能
java-security - Python安全 - 使用技能
python-security - 密钥管理 - 使用技能
secrets-management
深度知识:如需ASP.NET Core安全文档,请使用工具,指定技术类型为mcp__documentation__fetch_docs。dotnet
Dependency Auditing
依赖项审计
bash
undefinedbash
undefined.NET built-in audit
.NET内置审计
dotnet list package --vulnerable
dotnet list package --vulnerable
Detailed audit with transitive dependencies
包含传递依赖项的详细审计
dotnet list package --vulnerable --include-transitive
dotnet list package --vulnerable --include-transitive
Check outdated packages
检查过时包
dotnet list package --outdated
dotnet list package --outdated
Snyk for .NET
使用Snyk进行.NET审计
snyk test
undefinedsnyk test
undefinedCI/CD Integration
CI/CD集成
yaml
undefinedyaml
undefinedGitHub Actions
GitHub Actions
- name: Security audit run: | dotnet list package --vulnerable --include-transitive dotnet tool install -g snyk snyk test
undefined- name: Security audit run: | dotnet list package --vulnerable --include-transitive dotnet tool install -g snyk snyk test
undefinedNuGet.config Security
NuGet.config安全配置
xml
<configuration>
<packageSources>
<!-- Use only trusted sources -->
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<!-- Use environment variables for private feeds -->
</packageSourceCredentials>
</configuration>xml
<configuration>
<packageSources>
<!-- 仅使用可信源 -->
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<!-- 对私有源使用环境变量 -->
</packageSourceCredentials>
</configuration>ASP.NET Core Security Configuration
ASP.NET Core安全配置
Program.cs Security Setup
Program.cs安全设置
csharp
var builder = WebApplication.CreateBuilder(args);
// Security headers
builder.Services.AddHsts(options =>
{
options.MaxAge = TimeSpan.FromDays(365);
options.IncludeSubDomains = true;
options.Preload = true;
});
// CORS configuration
builder.Services.AddCors(options =>
{
options.AddPolicy("Production", policy =>
{
policy.WithOrigins("https://myapp.com")
.AllowCredentials()
.WithMethods("GET", "POST", "PUT", "DELETE")
.WithHeaders("Authorization", "Content-Type");
});
});
// Authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
};
});
// Rate limiting (.NET 7+)
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("login", limiter =>
{
limiter.Window = TimeSpan.FromMinutes(15);
limiter.PermitLimit = 5;
limiter.QueueLimit = 0;
});
});
var app = builder.Build();
// Security middleware order matters
app.UseHsts();
app.UseHttpsRedirection();
app.UseCors("Production");
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();csharp
var builder = WebApplication.CreateBuilder(args);
// 安全标头
builder.Services.AddHsts(options =>
{
options.MaxAge = TimeSpan.FromDays(365);
options.IncludeSubDomains = true;
options.Preload = true;
});
// CORS配置
builder.Services.AddCors(options =>
{
options.AddPolicy("Production", policy =>
{
policy.WithOrigins("https://myapp.com")
.AllowCredentials()
.WithMethods("GET", "POST", "PUT", "DELETE")
.WithHeaders("Authorization", "Content-Type");
});
});
// 身份验证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
};
});
// 限流(.NET 7+)
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("login", limiter =>
{
limiter.Window = TimeSpan.FromMinutes(15);
limiter.PermitLimit = 5;
limiter.QueueLimit = 0;
});
});
var app = builder.Build();
// 安全中间件顺序很重要
app.UseHsts();
app.UseHttpsRedirection();
app.UseCors("Production");
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();Security Headers Middleware
安全标头中间件
csharp
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
context.Response.Headers.Add("X-Frame-Options", "DENY");
context.Response.Headers.Add("X-XSS-Protection", "0"); // Use CSP instead
context.Response.Headers.Add("Referrer-Policy", "strict-origin-when-cross-origin");
context.Response.Headers.Add("Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'");
await next();
});csharp
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
context.Response.Headers.Add("X-Frame-Options", "DENY");
context.Response.Headers.Add("X-XSS-Protection", "0"); // 建议使用CSP替代
context.Response.Headers.Add("Referrer-Policy", "strict-origin-when-cross-origin");
context.Response.Headers.Add("Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'");
await next();
});SQL Injection Prevention
SQL注入防护
Entity Framework Core - Safe
Entity Framework Core - 安全写法
csharp
// SAFE - LINQ queries
var user = await context.Users
.FirstOrDefaultAsync(u => u.Email == email);
// SAFE - Parameterized raw SQL
var users = await context.Users
.FromSqlRaw("SELECT * FROM Users WHERE Email = {0}", email)
.ToListAsync();
// SAFE - Interpolated (converted to parameters)
var users = await context.Users
.FromSqlInterpolated($"SELECT * FROM Users WHERE Email = {email}")
.ToListAsync();csharp
// 安全 - LINQ查询
var user = await context.Users
.FirstOrDefaultAsync(u => u.Email == email);
// 安全 - 参数化原生SQL
var users = await context.Users
.FromSqlRaw("SELECT * FROM Users WHERE Email = {0}", email)
.ToListAsync();
// 安全 - 插值语法(会转换为参数)
var users = await context.Users
.FromSqlInterpolated($"SELECT * FROM Users WHERE Email = {email}")
.ToListAsync();Entity Framework Core - UNSAFE
Entity Framework Core - 不安全写法
csharp
// UNSAFE - String concatenation
var query = $"SELECT * FROM Users WHERE Email = '{email}'"; // NEVER!
var users = await context.Users.FromSqlRaw(query).ToListAsync();
// UNSAFE - FormattableString with raw
var users = await context.Users
.FromSqlRaw($"SELECT * FROM Users WHERE Email = '{email}'") // NEVER!
.ToListAsync();csharp
// 不安全 - 字符串拼接
var query = $"SELECT * FROM Users WHERE Email = '{email}'"; // 绝对禁止!
var users = await context.Users.FromSqlRaw(query).ToListAsync();
// 不安全 - 直接使用插值字符串的原生SQL
var users = await context.Users
.FromSqlRaw($"SELECT * FROM Users WHERE Email = '{email}'") // 绝对禁止!
.ToListAsync();Dapper - Safe
Dapper - 安全写法
csharp
// SAFE - Anonymous parameters
var user = await connection.QueryFirstOrDefaultAsync<User>(
"SELECT * FROM Users WHERE Email = @Email",
new { Email = email }
);
// SAFE - DynamicParameters
var parameters = new DynamicParameters();
parameters.Add("Email", email);
var user = await connection.QueryFirstOrDefaultAsync<User>(
"SELECT * FROM Users WHERE Email = @Email",
parameters
);csharp
// 安全 - 匿名参数
var user = await connection.QueryFirstOrDefaultAsync<User>(
"SELECT * FROM Users WHERE Email = @Email",
new { Email = email }
);
// 安全 - DynamicParameters
var parameters = new DynamicParameters();
parameters.Add("Email", email);
var user = await connection.QueryFirstOrDefaultAsync<User>(
"SELECT * FROM Users WHERE Email = @Email",
parameters
);XSS Prevention
XSS防护
Razor Pages (Auto-encoding)
Razor Pages(自动编码)
html
<!-- SAFE - Auto-encoded -->
<p>@Model.UserInput</p>
<!-- UNSAFE - Raw HTML -->
<p>@Html.Raw(Model.UserInput)</p> <!-- Avoid if possible -->html
<!-- 安全 - 自动编码 -->
<p>@Model.UserInput</p>
<!-- 不安全 - 原始HTML -->
<p>@Html.Raw(Model.UserInput)</p> <!-- 尽可能避免使用 -->Manual Sanitization
手动清理
csharp
using Ganss.Xss;
var sanitizer = new HtmlSanitizer();
sanitizer.AllowedTags.Add("p");
sanitizer.AllowedTags.Add("b");
sanitizer.AllowedTags.Add("i");
string safeHtml = sanitizer.Sanitize(userInput);csharp
using Ganss.Xss;
var sanitizer = new HtmlSanitizer();
sanitizer.AllowedTags.Add("p");
sanitizer.AllowedTags.Add("b");
sanitizer.AllowedTags.Add("i");
string safeHtml = sanitizer.Sanitize(userInput);API Response Encoding
API响应编码
csharp
using System.Text.Encodings.Web;
var encoder = HtmlEncoder.Default;
var safeString = encoder.Encode(userInput);csharp
using System.Text.Encodings.Web;
var encoder = HtmlEncoder.Default;
var safeString = encoder.Encode(userInput);Authentication & Authorization
身份验证与授权
JWT Token Generation
JWT令牌生成
csharp
public class JwtService
{
private readonly IConfiguration _config;
public JwtService(IConfiguration config) => _config = config;
public string GenerateToken(User user)
{
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.Role, user.Role)
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}csharp
public class JwtService
{
private readonly IConfiguration _config;
public JwtService(IConfiguration config) => _config = config;
public string GenerateToken(User user)
{
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.Role, user.Role)
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}Password Hashing with Identity
使用Identity进行密码哈希
csharp
// Use ASP.NET Core Identity's PasswordHasher
var hasher = new PasswordHasher<User>();
// Hash password
string hashed = hasher.HashPassword(user, password);
// Verify password
var result = hasher.VerifyHashedPassword(user, hashed, password);
if (result == PasswordVerificationResult.Success)
{
// Password matches
}csharp
// 使用ASP.NET Core Identity的PasswordHasher
var hasher = new PasswordHasher<User>();
// 哈希密码
string hashed = hasher.HashPassword(user, password);
// 验证密码
var result = hasher.VerifyHashedPassword(user, hashed, password);
if (result == PasswordVerificationResult.Success)
{
// 密码匹配
}Authorization Policies
授权策略
csharp
// Program.cs
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AdminOnly", policy =>
policy.RequireRole("Admin"));
options.AddPolicy("ResourceOwner", policy =>
policy.Requirements.Add(new ResourceOwnerRequirement()));
});
// Custom requirement handler
public class ResourceOwnerHandler : AuthorizationHandler<ResourceOwnerRequirement, Resource>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
ResourceOwnerRequirement requirement,
Resource resource)
{
var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
if (resource.OwnerId == userId)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
// Controller usage
[Authorize(Policy = "AdminOnly")]
public IActionResult AdminDashboard() => View();csharp
// Program.cs
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AdminOnly", policy =>
policy.RequireRole("Admin"));
options.AddPolicy("ResourceOwner", policy =>
policy.Requirements.Add(new ResourceOwnerRequirement()));
});
// 自定义需求处理器
public class ResourceOwnerHandler : AuthorizationHandler<ResourceOwnerRequirement, Resource>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
ResourceOwnerRequirement requirement,
Resource resource)
{
var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
if (resource.OwnerId == userId)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
// 控制器使用
[Authorize(Policy = "AdminOnly")]
public IActionResult AdminDashboard() => View();Input Validation
输入验证
Data Annotations
数据注解
csharp
public class CreateUserRequest
{
[Required]
[EmailAddress]
[StringLength(255)]
public string Email { get; set; } = default!;
[Required]
[StringLength(128, MinimumLength = 12)]
[RegularExpression(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).+$",
ErrorMessage = "Password must contain uppercase, lowercase, number and special character")]
public string Password { get; set; } = default!;
[Required]
[StringLength(100, MinimumLength = 2)]
[RegularExpression(@"^[a-zA-Z\s\-']+$")]
public string Name { get; set; } = default!;
}
[HttpPost]
public IActionResult CreateUser([FromBody] CreateUserRequest request)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
// request is validated
}csharp
public class CreateUserRequest
{
[Required]
[EmailAddress]
[StringLength(255)]
public string Email { get; set; } = default!;
[Required]
[StringLength(128, MinimumLength = 12)]
[RegularExpression(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).+$",
ErrorMessage = "密码必须包含大写字母、小写字母、数字和特殊字符")]
public string Password { get; set; } = default!;
[Required]
[StringLength(100, MinimumLength = 2)]
[RegularExpression(@"^[a-zA-Z\s\-']+$")]
public string Name { get; set; } = default!;
}
[HttpPost]
public IActionResult CreateUser([FromBody] CreateUserRequest request)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
// 请求已通过验证
}FluentValidation
FluentValidation
csharp
public class CreateUserValidator : AbstractValidator<CreateUserRequest>
{
public CreateUserValidator()
{
RuleFor(x => x.Email)
.NotEmpty()
.EmailAddress()
.MaximumLength(255);
RuleFor(x => x.Password)
.NotEmpty()
.MinimumLength(12)
.MaximumLength(128)
.Matches(@"[A-Z]").WithMessage("Must contain uppercase")
.Matches(@"[a-z]").WithMessage("Must contain lowercase")
.Matches(@"\d").WithMessage("Must contain digit")
.Matches(@"[@$!%*?&]").WithMessage("Must contain special character");
RuleFor(x => x.Name)
.NotEmpty()
.Length(2, 100)
.Matches(@"^[a-zA-Z\s\-']+$");
}
}csharp
public class CreateUserValidator : AbstractValidator<CreateUserRequest>
{
public CreateUserValidator()
{
RuleFor(x => x.Email)
.NotEmpty()
.EmailAddress()
.MaximumLength(255);
RuleFor(x => x.Password)
.NotEmpty()
.MinimumLength(12)
.MaximumLength(128)
.Matches(@"[A-Z]").WithMessage("必须包含大写字母")
.Matches(@"[a-z]").WithMessage("必须包含小写字母")
.Matches(@"\d").WithMessage("必须包含数字")
.Matches(@"[@$!%*?&]").WithMessage("必须包含特殊字符");
RuleFor(x => x.Name)
.NotEmpty()
.Length(2, 100)
.Matches(@"^[a-zA-Z\s\-']+$");
}
}Secure File Upload
安全文件上传
csharp
[HttpPost("upload")]
[RequestSizeLimit(10 * 1024 * 1024)] // 10 MB
public async Task<IActionResult> Upload(IFormFile file)
{
// Validate content type
var allowedTypes = new[] { "image/jpeg", "image/png", "application/pdf" };
if (!allowedTypes.Contains(file.ContentType))
return BadRequest("File type not allowed");
// Validate file extension
var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".pdf" };
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (!allowedExtensions.Contains(extension))
return BadRequest("File extension not allowed");
// Generate safe filename
var safeName = $"{Guid.NewGuid()}{extension}";
var uploadPath = Path.Combine(_uploadDirectory, safeName);
// Save file
await using var stream = new FileStream(uploadPath, FileMode.Create);
await file.CopyToAsync(stream);
return Ok(new { filename = safeName });
}csharp
[HttpPost("upload")]
[RequestSizeLimit(10 * 1024 * 1024)] // 10 MB
public async Task<IActionResult> Upload(IFormFile file)
{
// 验证内容类型
var allowedTypes = new[] { "image/jpeg", "image/png", "application/pdf" };
if (!allowedTypes.Contains(file.ContentType))
return BadRequest("不允许的文件类型");
// 验证文件扩展名
var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".pdf" };
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (!allowedExtensions.Contains(extension))
return BadRequest("不允许的文件扩展名");
// 生成安全文件名
var safeName = $"{Guid.NewGuid()}{extension}";
var uploadPath = Path.Combine(_uploadDirectory, safeName);
// 保存文件
await using var stream = new FileStream(uploadPath, FileMode.Create);
await file.CopyToAsync(stream);
return Ok(new { filename = safeName });
}Secrets Management
密钥管理
User Secrets (Development)
用户密钥(开发环境)
bash
undefinedbash
undefinedInitialize user secrets
初始化用户密钥
dotnet user-secrets init
dotnet user-secrets init
Set secrets
设置密钥
dotnet user-secrets set "Jwt:Key" "your-secret-key"
dotnet user-secrets set "ConnectionStrings:Default" "your-connection-string"
undefineddotnet user-secrets set "Jwt:Key" "your-secret-key"
dotnet user-secrets set "ConnectionStrings:Default" "your-connection-string"
undefinedappsettings.json (DO NOT store secrets)
appsettings.json(请勿存储密钥)
json
{
"Jwt": {
"Issuer": "https://myapp.com",
"Audience": "https://myapp.com"
// Key should come from environment or secrets manager
}
}json
{
"Jwt": {
"Issuer": "https://myapp.com",
"Audience": "https://myapp.com"
// 密钥应来自环境变量或密钥管理器
}
}Environment Variables
环境变量
csharp
// Program.cs - Load from environment
builder.Configuration.AddEnvironmentVariables();
// Access
var jwtKey = builder.Configuration["Jwt:Key"]
?? throw new InvalidOperationException("JWT Key not configured");csharp
// Program.cs - 从环境变量加载
builder.Configuration.AddEnvironmentVariables();
// 访问
var jwtKey = builder.Configuration["Jwt:Key"]
?? throw new InvalidOperationException("未配置JWT密钥");Azure Key Vault Integration
Azure Key Vault集成
csharp
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{vaultName}.vault.azure.net/"),
new DefaultAzureCredential()
);csharp
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{vaultName}.vault.azure.net/"),
new DefaultAzureCredential()
);Logging Security Events
安全事件日志记录
csharp
public class SecurityLogger
{
private readonly ILogger<SecurityLogger> _logger;
public SecurityLogger(ILogger<SecurityLogger> logger) => _logger = logger;
public void LogLoginAttempt(string username, bool success, string ipAddress)
{
_logger.LogInformation(
"Login attempt: User={Username}, Success={Success}, IP={IpAddress}",
username, success, ipAddress
);
}
public void LogAccessDenied(string userId, string resource, string ipAddress)
{
_logger.LogWarning(
"Access denied: User={UserId}, Resource={Resource}, IP={IpAddress}",
userId, resource, ipAddress
);
}
// NEVER log sensitive data
// _logger.LogInformation("Password: {Password}", password); // NEVER!
}csharp
public class SecurityLogger
{
private readonly ILogger<SecurityLogger> _logger;
public SecurityLogger(ILogger<SecurityLogger> logger) => _logger = logger;
public void LogLoginAttempt(string username, bool success, string ipAddress)
{
_logger.LogInformation(
"登录尝试:用户={Username}, 成功={Success}, IP={IpAddress}",
username, success, ipAddress
);
}
public void LogAccessDenied(string userId, string resource, string ipAddress)
{
_logger.LogWarning(
"访问被拒绝:用户={UserId}, 资源={Resource}, IP={IpAddress}",
userId, resource, ipAddress
);
}
// 绝对不要记录敏感数据
// _logger.LogInformation("密码: {Password}", password); // 绝对禁止!
}Anti-Patterns
反模式
| Anti-Pattern | Why It's Bad | Correct Approach |
|---|---|---|
| String interpolation in SQL | SQL injection | Use parameterized queries |
| XSS vulnerability | Use default encoding |
| Storing secrets in appsettings | Secret exposure | Use User Secrets/Key Vault |
| No authentication | Apply selectively |
| Disabling HTTPS redirection | Man-in-the-middle | Keep HTTPS enabled |
| Custom crypto implementation | Weak encryption | Use built-in libraries |
| Catching all exceptions | Hides security issues | Log and handle specifically |
| 反模式 | 危害 | 正确做法 |
|---|---|---|
| SQL中使用字符串插值 | 存在SQL注入风险 | 使用参数化查询 |
| 存在XSS漏洞 | 使用默认编码 |
| 在appsettings中存储密钥 | 密钥泄露 | 使用用户密钥/密钥保管库 |
全局使用 | 无身份验证保护 | 选择性应用 |
| 禁用HTTPS重定向 | 存在中间人攻击风险 | 保持HTTPS启用 |
| 自定义加密实现 | 加密强度不足 | 使用内置库 |
| 捕获所有异常 | 隐藏安全问题 | 针对性记录和处理 |
Quick Troubleshooting
快速排查指南
| Issue | Likely Cause | Solution |
|---|---|---|
| 401 Unauthorized | JWT validation failed | Check issuer, audience, key |
| CORS error | Origin not allowed | Add origin to CORS policy |
| Rate limit triggered | Too many requests | Adjust rate limiter settings |
| Password validation fails | Policy requirements | Check Identity password options |
| NuGet vulnerability | Outdated package | Update to patched version |
| User Secrets not loading | Not in Development | Check |
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 401未授权 | JWT验证失败 | 检查颁发者、受众、密钥 |
| CORS错误 | 来源未被允许 | 将来源添加到CORS策略 |
| 触发限流 | 请求次数过多 | 调整限流设置 |
| 密码验证失败 | 策略要求不满足 | 检查Identity密码选项 |
| NuGet漏洞 | 包版本过时 | 更新到已修复的版本 |
| 用户密钥未加载 | 不在开发环境 | 检查 |
Security Scanning Commands
安全扫描命令
bash
undefinedbash
undefinedDependency audit
依赖项审计
dotnet list package --vulnerable --include-transitive
dotnet list package --vulnerable --include-transitive
Security analyzers (add NuGet packages)
安全分析器(需添加NuGet包)
Microsoft.CodeAnalysis.NetAnalyzers
Microsoft.CodeAnalysis.NetAnalyzers
SecurityCodeScan.VS2019
SecurityCodeScan.VS2019
Snyk
Snyk扫描
snyk test
snyk test
Check for secrets
检查密钥泄露
gitleaks detect
trufflehog git file://.
gitleaks detect
trufflehog git file://.
SAST with Semgrep
使用Semgrep进行SAST扫描
semgrep --config=p/csharp .
undefinedsemgrep --config=p/csharp .
undefinedRelated Skills
相关技能
- OWASP Top 10:2025
- OWASP General
- Secrets Management
- Supply Chain Security
- OWASP Top 10:2025
- 通用OWASP
- 密钥管理
- 供应链安全