Web开发:使用Ocelot+Nacos+WebApi作简单网关鉴权

一、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}"));
        }
    }

}

四、后端获取用户相关信息

直接读请求头就好了

相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
大蓝头1 天前
安装包UI美化之路-nsNiuniuSkin全新UI调试与预览方法
ui·electron·安装包·截图控件·截屏控件
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄1 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端