上一篇介紹了在不整合Consul的狀況下,如何使用identity server。在實際應用環境中,內部服務通常是不對外暴露的,因此如今咱們把consul考慮進來,稍做修改就能夠了。html
環境介紹,咱們有一個OrderService和PartnerService,其中的/api/default是授權限保護的,還有一個ocelot網關和identity server4的權限服務。web
能夠參照以前的文章先把權限服務集成到consul。json
大體流程是:首先在網關注冊認證服務,修改認證服務資源,在api服務中集成認證api
修改Startup架構
// IdentityServer #region IdentityServerAuthenticationOptions => need to refactor Action<IdentityServerAuthenticationOptions> isaOptClient = option => { option.Authority = Configuration["IdentityService:Uri"]; option.ApiName = "serviceorder"; option.RequireHttpsMetadata = Convert.ToBoolean(Configuration["IdentityService:UseHttps"]); option.SupportedTokens = SupportedTokens.Both; option.ApiSecret = Configuration["IdentityService:ApiSecrets:orderservice"]; }; Action<IdentityServerAuthenticationOptions> isaOptProduct = option => { option.Authority = Configuration["IdentityService:Uri"]; option.ApiName = "servicepartner"; option.RequireHttpsMetadata = Convert.ToBoolean(Configuration["IdentityService:UseHttps"]); option.SupportedTokens = SupportedTokens.Both; option.ApiSecret = Configuration["IdentityService:ApiSecrets:partnerservice"]; }; #endregion services.AddAuthentication() .AddIdentityServerAuthentication("PartnerServiceKey", isaOptProduct) .AddIdentityServerAuthentication("OrderServiceKey", isaOptClient);
配置文件以下mvc
{ "Swagger": { "DocName": "ZJ.ApiGateway", "Version": "v1", "Title": "API Gateway Service", "ServiceDocNames": "serviceorder,servicepartner,serviceauthorize" // Swagger doc name list }, "Logging": { "LogLevel": { "Default": "Warning" } }, "IdentityService": { "Uri": "http://192.168.8.157:5100", "UseHttps": false, "ApiSecrets": { "orderservice": "ordersecret", "partnerservice": "partnersecret" } }, "AllowedHosts": "*" }
修改ocelotsettings.json,給權限服務加上路由,若是須要swagger,也加上app
// API:Service.Authorize // --> swagger part { "DownstreamPathTemplate": "/doc/serviceauthorize-gateway/swagger.json", "DownstreamScheme": "http", "ServiceName": "Service.Authorize", "LoadBalancer": "RoundRobin", "UseServiceDiscovery": true, "UpstreamPathTemplate": "/doc/serviceauthorize/swagger.json", "UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ] }, { "UseServiceDiscovery": true, // use Consul service discovery "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "ServiceName": "Service.Authorize", "LoadBalancerOptions": { "Type": "RoundRobin" }, "UpstreamPathTemplate": "/api/Serviceauthorize/{url}", "UpstreamHttpMethod": [ "Get", "Post" ], "ReRoutesCaseSensitive": false, // non case sensitive "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 2, // 容許多少個異常請求 "DurationOfBreak": 5000, // 熔斷的時間,單位爲毫秒 "TimeoutValue": 3000 // 若是下游請求的處理時間超過多少則視如該請求超時 } }
修改IdentityServerConfig類ide
public static class IdentityServerConfig { /// <summary> /// 容許使用認證服務的api列表 /// </summary> /// <returns></returns> public static IEnumerable<ApiResource> GetApiResources() { return new List<ApiResource> { new ApiResource("serviceorder", "Default (all) API"), new ApiResource("servicepartner", "Default (all) API1"), }; } /// <summary> /// /// </summary> /// <returns></returns> public static IEnumerable<IdentityResource> GetIdentityResources() { return new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile(), new IdentityResources.Email(), new IdentityResources.Phone() }; } /// <summary> /// 容許使用認證服務的應用客戶端 /// </summary> /// <returns></returns> public static IEnumerable<Client> GetClients(IConfiguration Configuration) { return new List<Client> { new Client { ClientId = "default_web_client", ClientName="default_name", AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, AllowedScopes = { "serviceorder", "servicepartner", }, ClientSecrets = new[]{ new Secret("secret1".Sha256())} }, new Client { ClientId = "default_app_client", ClientName="default_name11", AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, AllowedScopes = { "serviceorder", }, ClientSecrets = new[]{ new Secret("secret2".Sha256())} }, new Client { ClientId = "default_mvc_client", ClientName="default_name111", AllowedGrantTypes = GrantTypes.Implicit, RedirectUris = { Configuration["Clients:MvcClient:RedirectUri"] }, AllowedScopes = { "serviceorder", }, ClientSecrets = new[]{ new Secret("secret3".Sha256())} } }; } }
注意這裏的Clients,這麼設定的目的是當使用default_web_client時能夠訪問servicePartner以及serviceOrder,當使用default_app_client時只能訪問serviceorder微服務
修改ConfigureServices測試
// identity server services.AddMvcCore().AddAuthorization().AddJsonFormatters(); services.AddAuthentication(_appConfiguration["IdentityService:DefaultScheme"]).AddIdentityServerAuthentication(_appConfiguration["IdentityService:DefaultScheme"], options => { options.Authority = _appConfiguration["IdentityService:Uri"]; options.RequireHttpsMetadata = false; options.ApiName = "serviceorder"; // match with configuration in IdentityServer });
配置文件以下,注意defaultScheme必須和網關中配置的AddIdentityServerAuthentication一致
"IdentityService": { "Uri": "http://192.168.8.157:5100", "DefaultScheme": "OrderServiceKey", "UseHttps": false, "ApiSecret": "clientsecret" }
發佈到iis開始測試,個人測試環境中order服務端口是5000,partner服務端口是5001,認證服務端口5100,api網關端口5555
首先請求token,地址填寫api網關地址,client_id、client_secret和權限服務中設置的一致,其餘按下圖填寫
成功請求到token,按照咱們在權限服務中的配置,這個token是屬於default_web_client的,那麼它能夠用在serviceorder和servicepartner這兩個api中
請求serviceorder,能夠正常得到結果,注意在Auth選項卡中選擇Bearer Token並填寫剛纔取得的access_token
請求servicepartner,也能夠正常返回結果
如今咱們換一個clientId,換成default_app_client,理論上它只能請求serviceorder,而不能請求servicepartner
能夠看到請求servicepartner時返回了401 Unauthorized,測試經過。
上述方式有一個較大的問題,那就是client_id對應的client_secret會暴露在客戶端的請求體中。既然驗證請求要通過api網關,那能夠考慮在api網關作一次人工轉發,在請求體中加上這個client_secret,具體能夠看參考文章,此處再也不展開。
到這一步,微服務架構已經基本成型,consul做爲服務中心統籌管理全部的api服務,獨立的權限服務經過consul提供權限驗證、用戶註冊、註銷等功能。下一步須要重構代碼,從新梳理項目結構,整理完成後接入CAP就基本能夠開始開發。
參考文章: