首页 > 其他分享 >11.Feign组件介入Nacos微服务

11.Feign组件介入Nacos微服务

时间:2024-02-25 11:45:47浏览次数:21  
标签:11 Feign httpContextAccessor builder Nacos user new public

创建三个项目Summerboot.Feign,Summerboot.Client(http://192.168.10.13:5197),NacosService(http://192.168.10.13:5199)

注意Summerboot.Client依赖Summerboot.Feign。

安装包:SummerBoot

Summerboot.Client客户端是用来调用Feign组件

先添加一个JWT配置类

/// <summary>
/// JWT配置类
/// </summary>
public class JwtTokenOption
{
    /// <summary>
    /// Token 过期时间,默认为60分钟
    /// </summary>
    public int TokenExpireTime { get; set; } = 60;
    /// <summary>
    /// 接收人
    /// </summary>
    public string Audience { get; set; }
    /// <summary>
    /// 秘钥
    /// </summary>
    public string SecurityKey { get; set; }
    /// <summary>
    /// 签发人
    /// </summary>
    public string Issuer { get; set; }
    
}

 

 

NacosService项目

UserController控制器

[ApiController]
[Route("[controller]/[action]")]
public class UserController:ControllerBase
{
    [HttpGet]
    public List<UserInfo> GetUsers()
    {
        List<UserInfo> result = new()
        {
            new(){Id = 1,NickName = "张三"},
            new(){Id = 2,NickName = "李四"}
        };
        return result;
    }


    [HttpPost]
    public UserInfo PostUser([FromBody]UserInfo user)
    {
        return user;
    }

    /// <summary>
    /// 测试Feign调用受保护的资源
    /// </summary>
    /// <param name="user"></param>
    /// <returns></returns>
    [HttpPost]
    [Authorize]
    public UserInfo TestAuthentication([FromBody] UserInfo user)
    {
        return user;
    }

}

 

appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "nacos": {
    "ServerAddresses": [
      "http://127.0.0.1:8848"
    ],
    "DefaultTimeOut": 15000,
    //请求超时时间
    "Namespace": "6c0da0b7-eb66-4c15-b73e-15b983d07548",
    //命名空间id
    "ListenInterval": 1000,
    //监听间隔时间
    "ServiceName": "NacosService",
    //服务名称
    "GroupName": "DEFAULT_GROUP",
    // 默认分组名称
    "ClusterName": "DEFAULT",
    // 如果去掉这个配置项,系统会自动获取服务IP(建议去掉这个配置)
//     "Ip": "localhost",//注册中心,服务调用的IP地址
//     "PreferredNetworks": "localhost", //首选网络
//    // 如果去掉这个配置项,系统会自动获取服务运行的端口号(建议去掉这个配置)
//     "Port": 5199, // // 写0 表示80端口()
    "Weight": 100,
    "RegisterEnabled": true,
    "InstanceEnabled": true,
    "Ephemeral": true,
    "Secure": false,
    //表示当前服务是否时安全实例,用于标识访问的时候是否要启用 https
    "AccessKey": "",
    "SecretKey": "",
    "UserName": "",
    "Password": "",
    "ConfigUseRpc": false,
    "NamingUseRpc": false,
    "NamingLoadCacheAtStart": "",
    "LBStrategy": "WeightRandom",
    // 负载均衡策略:WeightRandom(随机), WeightRoundRobin(轮询)
    "Metadata": {
      "aa": "bb",
      "cc": "dd"
    }
  }
}

 

 

 

Summerboot.Client项目

appsettings.Development.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "nacos": {
    //--------使用nacos则serviceAddress和namespaceId必填------
    //nacos服务地址,如http://172.16.189.242:8848
    "serviceAddress": "http://127.0.0.1:8848/",
    //命名空间id,如832e754e-e845-47db-8acc-46ae3819b638或者public
    "namespaceId": "6c0da0b7-eb66-4c15-b73e-15b983d07548",

    //--------如果只是访问nacos中的微服务,则仅配置lbStrategy即可,defaultNacosGroupName和defaultNacosNamespaceId选填------
    //客户端负载均衡算法,一个服务下有多个实例,lbStrategy用来挑选服务下的实例,默认为Random(随机),也可以选择WeightRandom(根据服务权重加权后再随机)
    "lbStrategy": "Random",
    //defaultNacosGroupName,选填,为FeignClient注解中NacosGroupName的默认值,为空则默认为DEFAULT_GROUP
    "defaultNacosGroupName": "",
    //defaultNacosNamespaceId,选填,为FeignClient注解中NacosNamespaceId的默认值,为空则默认为public
    "defaultNacosNamespaceId": "",

    //--------如果需要使用nacos配置中心,则ConfigurationOption必填,允许监听多个配置------
    "configurationOption": [
      {
        "namespaceId": "6c0da0b7-eb66-4c15-b73e-15b983d07548",
        //配置的分组
        "groupName": "DEFAULT_GROUP",
        //配置的dataId,
        "dataId": "app1-dev.json"
      }
    ],


    //-------如果是要将本应用注册为服务实例,则全部参数均需配置--------------

    //是否要把应用注册为服务实例
    "registerInstance": true,

    //要注册的服务名
    "serviceName": "Summerboot.Client",
    //服务的分组名
    "groupName": "DEFAULT_GROUP",
    //权重,一个服务下有多个实例,权重越高,访问到该实例的概率越大,比如有些实例所在的服务器配置高,那么权重就可以大一些,多引流到该实例,与上面的参数lbStrategy设置为WeightRandom搭配使用
    "weight": 1,
    //本应用对外的网络协议,http或https
    "protocol": "http"
    //本应用对外的端口号,比如5000
    //  ,"port": 5000

  }
}

创建MicroFeignClientController控制器

[ApiController]
[Route("[controller]/[action]")]
public class MicroFeignClientController
{
    private readonly INacosMicroService _nacosMicroService;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public MicroFeignClientController(
        INacosMicroService nacosMicroService
        , IHttpContextAccessor httpContextAccessor)
    {
        _nacosMicroService = nacosMicroService;
        _httpContextAccessor = httpContextAccessor;
    }

    [HttpGet]
    public async Task<List<UserInfo>> GetUsers()
    {
        return await _nacosMicroService.GetUsers();
    }
    
    /// <summary>
    /// 测试Feign调用受保护的资源
    /// </summary>
    /// <param name="user"></param>
    /// <returns></returns>
    [Authorize]
    [HttpPost]
    public async Task<UserInfo> TestAuthentication([FromBody]UserInfo user)
    {
        // var token = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
        // return await _nacosMicroService.TestAuthentication(user,token);
        
        return await _nacosMicroService.TestAuthentication(user);
    }
}

Program.cs配置

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();


builder.Services.AddSwaggerGen(p => {
    p.SwaggerDoc("v1", new OpenApiInfo()
    {
        Contact = new()
        {
            Email = "[email protected]",
            Name = "Feign组件学习",
            Url = new Uri("http://baidu.com")
        },
        Description = "Feign_Description",
        Title = "Feign_Title"
    });
    
    
    //Bearer 的scheme定义
    var securityScheme = new OpenApiSecurityScheme()
    {
        Description = "JWT Authorization 头使用Bearer 体系方案. 例: \"Authorization: Bearer 你的token\"",
        Name = "Authorization",
        //参数添加在头部
        In = ParameterLocation.Header,
        //使用Authorize头部
        Type = SecuritySchemeType.Http,
        //内容为以 bearer开头
        Scheme = "Bearer",
        BearerFormat = "JWT"
    };

    //把所有方法配置为增加bearer头部信息
    var securityRequirement = new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "JWT认证"
                }
            },
            new string[] {}
        }
    };

    //注册到swagger中
    p.AddSecurityDefinition("JWT认证", securityScheme);
    p.AddSecurityRequirement(securityRequirement);
    

    // 加载xml文档注释
    p.IncludeXmlComments(AppContext.BaseDirectory + Assembly.GetExecutingAssembly().GetName().Name + ".xml", true);

});

builder.Host.UseNacosConfiguration();
builder.Services.AddSummerBoot();
//启用配置中心 builder.Services.AddSummerBootFeign(p => { p.AddNacos(builder.Configuration,true); }); builder.Services.AddHttpContextAccessor(); #region JWT认证 var jwtOption = builder.Configuration.GetSection("JwtTokenOption"); builder.Services.Configure<JwtTokenOption>(jwtOption); JwtTokenOption jwtTokenOption = jwtOption.Get<JwtTokenOption>()!; // 添加认证服务 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(p => { var rsa = RSA.Create(); rsa.ImportRSAPrivateKey(Convert.FromBase64String(jwtTokenOption.SecurityKey), out _); SecurityKey securityKey = new RsaSecurityKey(rsa); // 校验JWT是否合法 p.TokenValidationParameters = new TokenValidationParameters() { ValidAlgorithms = new string[] { "RS256" }, ValidateIssuer = true, //是否验证Issuer ValidateAudience = true, //是否验证Audience ValidateLifetime = true, //是否验证失效时间 ClockSkew = TimeSpan.Zero, //时钟脉冲相位差 ValidateIssuerSigningKey = true, //是否验证SecurityKey ValidAudience = jwtTokenOption.Audience, //Audience ValidIssuer = jwtTokenOption.Issuer, //Issuer,这两项和前面签发jwt的设置一致 IssuerSigningKey = securityKey, //拿到SecurityKey }; }); builder.Services.AddAuthorization(); #endregion var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();

 

 

 

 

Summerboot.Feign项目

自定义拦截器对接口下的所有方法均生效,拦截器的应用场景主要是在请求前做一些操作,比如请求第三方业务接口前,需要先登录第三方系统,那么就可以在拦截器里先请求第三方登录接口,获取到凭证以后,放到header里,拦截器需要实现IRequestInterceptor接口
/// <summary>
/// 用于传递Token的拦截器
/// </summary>
public class TokenInterceptor:IRequestInterceptor
{
    private readonly IHttpContextAccessor _httpContextAccessor;


    public TokenInterceptor(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task ApplyAsync(RequestTemplate requestTemplate)
    {
        if (_httpContextAccessor.HttpContext != null)
        {
            var token = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
            if (!string.IsNullOrWhiteSpace(token))
            {
                requestTemplate.Headers.Add("Authorization",new List<string>{$"Bearer {token}"});
            }
        }
    }
}

 

 

添加一个INacosMicroService接口

[FeignClient(ServiceName = "NacosService"
    ,MicroServiceMode = true
    , NacosNamespaceId = "${nacos:namespaceId}"
    ,NacosGroupName = "${nacos:groupName}"
    ,InterceptorType = typeof(TokenInterceptor)
)]
public interface INacosMicroService
{
    [GetMapping("/user/GetUsers")]
    Task<List<UserInfo>> GetUsers();

    [PostMapping("/user/PostUser")]
    Task<UserInfo> PostUser([Body] UserInfo user);
    
    // /// <summary>
    // /// 测试Feign调用受保护的资源
    // /// </summary>
    // /// <param name="user"></param>
    // /// <returns></returns>
    // [PostMapping("/user/TestAuthentication")]
    // [Headers("Authorization:Bearer {{token}}")]
    // Task<UserInfo> TestAuthentication([Body] UserInfo user,string token);
    
    /// <summary>
    /// 测试Feign调用受保护的资源
    /// </summary>
    /// <param name="user"></param>
    /// <returns></returns>
    [PostMapping("/user/TestAuthentication")]
    Task<UserInfo> TestAuthentication([Body] UserInfo user);
}

 

标签:11,Feign,httpContextAccessor,builder,Nacos,user,new,public
From: https://www.cnblogs.com/MingQiu/p/18032202

相关文章

  • 10.Feign组件在NET中的简单使用
    安装包:SummerBootFeign是一种声明式服务调用组件,我们只需要声明一个接口并通过注解进行简单的配置(类似于Dao接口上面的Mapper注解一样)即可实现对HTTP接口的绑定。通过Feign,我们可以像调用本地方法一样来调用远程服务,而完全感觉不到这是在进行远程调用。Feign底层基于h......
  • P1137 旅行计划
    原题链接题解拓扑排序+dp。首先以入度为零的结点为起始结点,其游览城市数量为1,接下来每到下一结点,游览城市数++;即当前结点的游览城市数是上一结点的游览数+1,并取最大值。code #include<bits/stdc++.h>usingnamespacestd;constintN=1e5+5;inthead[N],Next[N*2],to[N......
  • 第11章硬件控制方法
    硬件的控制一般通过操作系统进行,应用不直接与硬件进行交互,其通过调用操作系统提供的api间接的控制硬件(也称系统调用)Windows控制硬件时主要借助的是输入输出指令,最具代表性的就是IN与OUT指令,这两个指令也是汇编语言的助记符IN指令:通过指定端口号的端口输入数据,并将其存储在CPU内......
  • P1197 [JSOI2008] 星球大战
    原题链接题解,请看题解区第一篇,看一遍就会了code#include<bits/stdc++.h>usingnamespacestd;intfa[400005]={0};intfinds(intnow){returnfa[now]=(fa[now]==now?now:finds(fa[now]));}vector<int>G[400005];intbroke[400005];intBroke[400005]={0};intm......
  • 暑期集训 Day11 —— 模拟赛复盘
    ${\color{Green}\mathrm{Problem\1:Subarray}}$签到失败...直接二进制分组,找出所有二进制位=0的方法。死因:二进制分组没想出来...${\color{White}\mathrm{}}$${\color{White}\mathrm{}}$${\color{White}\mathrm{}}$${\color{Green}\mathrm{Problem\2:......
  • 2-11. 受伤和死亡的逻辑和动画
    添加受伤和死亡动画片段通过新的层来实现受伤和死亡动画点击动画控制器右上角的+,然后新建一个Layer注意Weight要改成1,Blending要改成Additive受伤的话,我们通过hurt来触发,死亡我们通过isDead来控制在HurtLayer中,当hurt触发的时候,就会播放blueHurt动画,......
  • P4569 [BJWC2011] 禁忌 题解
    题目传送门前置知识AC自动机|矩阵加速递推解法对于一段固定的文本串,由于重叠的模式串不对伤害产生贡献,故考虑贪心,每碰到出现一个模式串将其分为一段,最终这个文本串的伤害就是划分次数。类似luoguP3193[HNOI2008]GT考试,令\(f_{i,j}\)表示前\(i\)个字符,当前运行到......
  • P1137 旅行计划
    原题链接题解一个节点的答案一定是最大父节点+1code#include<bits/stdc++.h>usingnamespacestd;intans[100005]={0};intin[100005]={0};vector<int>G[100005];structunit{intpos,order;};intmain(){intn,m;cin>>n>>m;for(inti......
  • 《程序是怎样跑起来的》——第11章 硬件控制方法
    一、应用和硬件1、在用C语言等高级编程语言开发的Windows应用中,大家很少能接触到直接控制硬件的指令。这是因为硬件的控制是由Windows全权负责的。Windows提供了通过应用来间接控制硬件的方法。利用操作系统提供的系统调用功能就可以实现对硬件的控制。示例:应用通过操作系统间接......
  • P4119 Ynoi2018 未来日记
    P4119Ynoi2018未来日记lxl出的题好duliu啊。感谢来自fr200110217102的博客题解P4119【Ynoi2018未来日记】。下标分块+值域分块+并查集其实一开始的方向应该是尝试线段树或者其它的动态维护的算法,直到时间复杂度和空间复杂度对不上,你才会想到——要分块!区间第\(k\)......