11.Feign组件介入Nacos微服务

创建三个项目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 = "1310734881@qq.com",
            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);
}

 

posted @ 2024-02-25 11:34  野码  阅读(48)  评论(0编辑  收藏  举报