上一篇介绍了在不整合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就基本能够开始开发。
参考文章: