封装WCF服务的API中调用WCF方法前验证Bearer Token(JWT)的最优实现方案咨询
Hey there! I totally get the frustration of repeating token validation code in every controller method—let's fix that with some clean, reusable solutions tailored to your ASP.NET Core + WCF scenario. Since you can't modify the WCF side, we'll handle all validation directly in your API layer.
Authorization filters run before your controller methods execute, making them perfect for centralizing token validation. You can apply this filter globally to all controllers, or selectively to specific ones/methods.
Step 1: Create the Filter Class
public class BearerTokenAuthorizationFilter : IAuthorizationFilter { // If you need dependency injection (e.g., a service to validate tokens), inject it here via constructor // private readonly ITokenValidationService _tokenValidationService; // public BearerTokenAuthorizationFilter(ITokenValidationService tokenValidationService) // { // _tokenValidationService = tokenValidationService; // } public void OnAuthorization(AuthorizationFilterContext context) { // Extract Bearer Token from request headers var authHeader = context.HttpContext.Request.Headers["Authorization"].FirstOrDefault(); var token = authHeader?.Split(" ").Last(); // Validate the token using your existing logic if (string.IsNullOrEmpty(token) || !CheckTokenValidity(token)) { // Return 401 Unauthorized if validation fails context.Result = new UnauthorizedObjectResult("Invalid or missing Bearer Token"); } } // Replace this with your existing checkToken logic private bool CheckTokenValidity(string token) { // Example: Verify token against a database, validate signature, check expiration, etc. return true; // Swap with your actual validation logic } }
Step 2: Register & Apply the Filter
Option A: Global Application (All Controllers)
Add this to your Program.cs (or Startup.cs if using older .NET versions):
builder.Services.AddControllers(options => { // Add the filter to all controller actions options.Filters.Add<BearerTokenAuthorizationFilter>(); }); // If you're using dependency injection in the filter, register it as a scoped service: // builder.Services.AddScoped<BearerTokenAuthorizationFilter>();
Option B: Selective Application (Specific Controllers/Methods)
Use the [ServiceFilter] attribute to apply the filter only where needed:
// Apply to entire controller [ServiceFilter(typeof(BearerTokenAuthorizationFilter))] public class CheckOutController : ControllerBase { private readonly CheckOutMarketService _checkOutMarketService; public CheckOutController(CheckOutMarketService checkOutMarketService) { _checkOutMarketService = checkOutMarketService; } // No more token validation code here! public async Task<IActionResult> GetReceipetByDocument(JsonInput input) { var response = await _checkOutMarketService.GetReceiptAsync(new ReceiptRequest { /* your params */ }); return Ok(response); } } // Or apply to a single method public class CheckOutController : ControllerBase { [ServiceFilter(typeof(BearerTokenAuthorizationFilter))] public async Task<IActionResult> GetReceipetByDocument(JsonInput input) { // Your business logic here } }
If your token is a standard JWT, leverage ASP.NET Core's official authentication middleware to avoid writing custom filters entirely. Even for custom tokens, you can extend this system to fit your validation logic.
Step 1: Install the Package
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Step 2: Configure Authentication & Authorization
Add this to Program.cs:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { // For standard JWT tokens, use these validation parameters options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = "your-token-issuer", // Replace with your issuer ValidAudience = "your-audience", // Replace with your audience IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-secret-signing-key")) }; // For custom token validation (non-standard JWT), override the events options.Events = new JwtBearerEvents { OnTokenValidated = context => { var rawToken = context.SecurityToken as JwtSecurityToken; if (!CheckTokenValidity(rawToken.RawData)) { context.Fail("Invalid custom token"); } return Task.CompletedTask; }, OnMessageReceived = context => { // Customize how you extract the token (e.g., from headers, query string) var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last(); if (!string.IsNullOrEmpty(token)) { context.Token = token; } return Task.CompletedTask; } }; }); // Enable authorization services builder.Services.AddAuthorization();
Step 3: Enable Middleware in the Pipeline
Add these lines before app.MapControllers():
app.UseAuthentication(); app.UseAuthorization();
Step 4: Protect Controllers/Methods
Just add the [Authorize] attribute wherever you need validation:
[Authorize] public class CheckOutController : ControllerBase { public async Task<IActionResult> GetReceipetByDocument(JsonInput input) { // Your business logic here—authentication is already handled! var response = await _checkOutMarketService.GetReceiptAsync(new ReceiptRequest { /* your params */ }); return Ok(response); } }
If you want to validate tokens for every incoming request (not just controller actions), use a custom middleware. This is great if you have non-MVC endpoints too, but you'll need to add exceptions for paths that don't require validation.
Step 1: Create the Middleware
public class BearerTokenMiddleware { private readonly RequestDelegate _next; public BearerTokenMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { // Skip validation for specific paths (e.g., health checks, public endpoints) var excludedPaths = new List<string> { "/health", "/public" }; if (excludedPaths.Any(path => context.Request.Path.StartsWithSegments(path))) { await _next(context); return; } // Extract and validate token var authHeader = context.Request.Headers["Authorization"].FirstOrDefault(); var token = authHeader?.Split(" ").Last(); if (string.IsNullOrEmpty(token) || !CheckTokenValidity(token)) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; await context.Response.WriteAsync("Invalid or missing Bearer Token"); return; } // Pass the request through if validation succeeds await _next(context); } private bool CheckTokenValidity(string token) { // Your existing token validation logic here return true; } }
Step 2: Register the Middleware
Add this to Program.cs after UseRouting and before UseAuthorization:
app.UseRouting(); app.UseMiddleware<BearerTokenMiddleware>(); app.UseAuthorization();
- Custom Authorization Filter: Best for MVC-focused APIs, gives you granular control over which controllers/methods are protected.
- Built-In Authentication: Ideal if you're using standard JWT tokens, leverages Microsoft's battle-tested security code.
- Custom Middleware: Perfect if you need to validate every request (including non-MVC endpoints), but requires extra work to exclude paths.
All of these solutions eliminate repetitive token validation code and keep your business logic clean!
内容的提问来源于stack exchange,提问作者Marduk

