一、Nuget包
我的是.NET9,注意包版本的问题,版本过大过小都可能会导致WebAPI跑不起来!

二、配置文件
1.appsettings.json
javascript
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Nacos": {
"ServerAddresses": [ "http://localhost:8848/" ], // 通信端口8848(不是控制台8080)
"Namespace": "",
"UserName": "nacos", //登录账号
"Password": "nacos",//登录密码
"ContextPath": "/nacos",
"LogLevel": "Debug",
"RequestTimeout": 10000,
"ServiceName": "OcelotGateway"//网关服务名称
}
}
2.ocelot.json
javascript
{
"Routes": [
{
"DownstreamPathTemplate": "/api/{catchAll}", //网关转发给后端服务的路径(转发出去的路径)。
"UpstreamPathTemplate": "/api/{catchAll}", //客户端请求网关的路径(过来的路径)
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ],
"DownstreamScheme": "http", //协议类型
"UseServiceDiscovery": true,//是否启用服务发现
"ServiceName": "GuangDongData", //服务名称,需与Nacos中注册的服务名称一致
"NacosNamespace": "public",
"NacosGroupName": "DEFAULT_GROUP",
"GroupName": "DEFAULT_GROUP",
"AuthenticationOptions": {
"AuthenticationProviderKey": "CustomGuidToken", //自定义认证处理器
"AllowedScopes": []
}
}
],
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Type": "Nacos"
}
}
}
三、鉴权认证代码
我这里暂时把token写死,实际去redis读就好了。
cs
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using Nacos;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Text.Json;
/// <summary>
/// 自定义认证处理器:校验请求头中的token是否等于写死的GUID
/// </summary>
public class CustomGuidTokenHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
// 写死的GUID Token
private const string FixedGuidToken = "f0e92635-5141-4ce2-9690-563ca18fdd3d";
public CustomGuidTokenHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
}
/// <summary>
/// 核心认证逻辑:校验token
/// </summary>
protected async override Task<AuthenticateResult> HandleAuthenticateAsync()
{
try
{
// 1. 从请求头获取token
var authHeader = Request.Headers["Authorization"].FirstOrDefault();
// 无token,认证失败 直接返回自定义401响应
if (string.IsNullOrEmpty(authHeader))
{
// 无token,认证失败 直接返回自定义401响应
Response.StatusCode = StatusCodes.Status401Unauthorized;
Response.ContentType = "application/json";
var error = JsonSerializer.Serialize(new { code = 401, message = "认证失败:未提供有效Token" });
await Response.WriteAsync(error);
return AuthenticateResult.Fail("未提供Token");
}
// 2. 解析token(兼容两种格式:带Bearer前缀/不带)
string token = authHeader.StartsWith("Bearer ")
? authHeader.Substring("Bearer ".Length).Trim()
: authHeader.Trim();
// 3. 校验token是否等于写死的GUID
if (token != FixedGuidToken)
{
// 无token,认证失败 直接返回自定义401响应
Response.StatusCode = StatusCodes.Status401Unauthorized;
Response.ContentType = "application/json";
var error = JsonSerializer.Serialize(new { code = 401, message = "认证失败:提供了无效的Token" });
await Response.WriteAsync(error);
return AuthenticateResult.Fail("无效Token");
}
// 4. 认证通过,构建用户身份
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "ValidUser"),//假设是这个用户名
new Claim(ClaimTypes.Role, "ApiAccess")//假设是这个角色
};
var identity = new ClaimsIdentity(claims, Scheme.Name);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
Context.Request.Headers["X-Custom-UserName"] = "ValidUser"; // 写进请求头,后端可通过读网关的请求头获取这些信息
Context.Request.Headers["X-Custom-UserRole"] = "ApiAccess"; // 写进请求头
return await Task.FromResult(AuthenticateResult.Success(ticket));
}
catch (Exception ex)
{
return await Task.FromResult(AuthenticateResult.Fail($"认证异常:{ex.Message}"));
}
}
}
四、后端获取用户相关信息
直接读请求头就好了
