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 = "[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);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章