root@jules : ~/workspace/logs/csharp-jwt-rbac-en.md
MES API Security: JWT + Custom Role Interceptors in .NET Core
MES systems have many sensitive endpoints (e.g., voiding work orders, transferring inventory). Simply checking if a user is logged in ([Authorize]) is highly insufficient. We must implement Role-Based Access Control down to the “button” level.
To avoid cluttering business logic with if(user.Role == "Admin"), we typically use a custom PermissionAttribute combined with an IAuthorizationFilter to intercept requests.
[AttributeUsage(AttributeTargets.Method)]
public class RequirePermissionAttribute : Attribute
{
public string PermissionCode { get; }
public RequirePermissionAttribute(string code) => PermissionCode = code;
}
public class PermissionFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
// Get the attribute on the routed method
var endpoint = context.HttpContext.GetEndpoint();
var attribute = endpoint?.Metadata.GetMetadata<RequirePermissionAttribute>();
if (attribute != null)
{
// Retrieve decoded JWT UserID from context
var userId = context.HttpContext.User.FindFirst("UserId")?.Value;
// Check DB or Cache for permissions (Redis recommended)
bool hasAccess = CheckUserPermissionFromDb(userId, attribute.PermissionCode);
if (!hasAccess)
{
// Throw 403 Forbidden
context.Result = new ForbidResult();
}
}
}
}
Usage in the Controller is incredibly elegant:
[HttpPost("DeleteOrder")]
[RequirePermission("ORDER_DELETE")] // Just attach this tag
public IActionResult DeleteOrder(string orderId) { ... }
This scheme is minimally invasive and, combined with Layui frontend button-hiding logic, creates a perfect RBAC security loop.