微服務網關從零搭建——(三)Ocelot網關 + identity4

增長驗證服務

1.建立名爲AuthService 的core 空項目html

2.修改startup文件json

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ConsulRegisterHelper;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace AuthService
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            //注入IdentityServer服務
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()//開發臨時證書
                .AddInMemoryClients(ApiConfig.GetClients())
                .AddInMemoryApiResources(ApiConfig.GetApiResources())
                .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()//添加自定義驗證
                .AddProfileService<ProfileService>(); ;
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseIdentityServer();
            app.RegisterConsul(lifetime, new ServiceEntity
            {
                IP = NetworkHelper.LocalIPAddress,
                Port = Convert.ToInt32(Configuration.GetSection("Setting")["Port"]),
                ServiceName = Configuration.GetSection("Setting")["ServiceName"],
                ConsulIP = Configuration.GetSection("Setting")["ConsulIP"],
                ConsulPort = Convert.ToInt32(Configuration.GetSection("Setting")["ConsulPort"])
            });
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("身份驗證服務啓動成功!");
            });
        }
    }
}
Startup

3.修改Programapi

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace AuthService
{
    public class Program
    {
        public static string StartPort;
        public static void Main(string[] args)
        {
            var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true)
.Build();
            StartPort = config.GetSection("Setting")["Port"];
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
             .UseUrls($"http://*:{StartPort}")
                .UseStartup<Startup>();
    }
}
Program

4.增長setting文件節點數組

"Setting": {
"Port": "7500",
"ServiceName": "authService",
"ConsulIP": "localhost",
"ConsulPort": "8500"
}app

5.增長身份驗證自定義用戶驗證相關async

using IdentityServer4.Models;
using IdentityServer4.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace AuthService
{
    public class ProfileService : IProfileService
    {
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var claims = context.Subject.Claims.ToList();
            context.IssuedClaims = claims.ToList();
        }

        public async Task IsActiveAsync(IsActiveContext context)
        {
            context.IsActive = true;
        }
    }
}
ProfileService.cs
using IdentityServer4.Models;
using IdentityServer4.Validation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace AuthService
{
    public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            //ToDo:驗證自定義用戶
            //LoginUser loginUser = null;
            bool isAuthenticated = context.UserName=="aaa"&&context.Password=="1"? true :false; //loginUserService.Authenticate(context.UserName, context.Password, out loginUser);
            if (!isAuthenticated)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "帳戶名密碼錯誤");
            }
            else
            {
                context.Result = new GrantValidationResult(
                    subject: context.UserName,
                    authenticationMethod: "custom",
                    claims: new Claim[] {
                        new Claim("Name", context.UserName),
                        new Claim("Id", ""),
                        new Claim("RealName", ""),
                        new Claim("Email", "")
                    }
                );
            }
            return Task.CompletedTask;
        }
    }
}
ResourceOwnerPasswordValidator.cs

6.增長示例數據ide

using IdentityServer4.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace AuthService
{
    /// <summary>
    /// 由於此處採用in-memory,因此硬編碼一些api,以及client
    /// </summary>
    public class ApiConfig
    {
        /// <summary>
        /// 定義ApiResource   這裏的資源(Resources)指的就是咱們的API
        /// </summary>
        /// <returns>ApiResource枚舉</returns>
        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new[]
            {
                new ApiResource("demoAPi", "測試API"),
            };
        }

        /// <summary>
        /// 定義受信任的客戶端 Client
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Client> GetClients()
        {
            return new[]
            {
                new Client
                {
                    ClientId = "OcelotDemo",//客戶端的標識,要是唯一的
                    ClientSecrets = new [] { new Secret("123456".Sha256()) },//客戶端密碼,進行了加密
                    AllowedGrantTypes = GrantTypes.ClientCredentials,//受權方式,這裏採用的是客戶端認證模式,只要ClientId,以及ClientSecrets正確便可訪問對應的AllowedScopes裏面的api資源
                    AllowedScopes = new [] { "demoAPi"}//定義這個客戶端能夠訪問的APi資源數組
                }
            };
        }
    }
}
ApiConfig.cs

改變網關

1.修改Startup.cs微服務

增長節點 post

 services.AddAuthentication()
               .AddIdentityServerAuthentication(Configuration.GetSection("Setting")["AuthScheme"], options => {
                   options.Authority = Configuration.GetSection("Setting")["AuthUrl"];
                   options.ApiName = Configuration.GetSection("Setting")["AuthApiName"];
                   options.SupportedTokens = SupportedTokens.Both;
                   options.RequireHttpsMetadata = false;
               });
ConfigureServices內容

2.修改網關配置測試

 //添加身份驗證
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "OcelotKey",
        "AllowedScopes": [ "demoAPi"]
      }
configuration.json

3.修改配置文件appsettings.json

 "Setting": {
    "Port": "5000",
    "AuthScheme": "OcelotKey", //須要和ReRoutes中的AuthenticationProviderKey一致
    "AuthUrl": "http://192.168.66.241:7500", // 驗證服務地址 注意 必須帶有http
    "AuthApiName": "demoAPi" //和 須要被驗證服務的服務名稱一致
  }
增長節點內容

注:

AuthUrl 中的 http://  必填 否則會出現500異常

AuthApiName  須要驗證服務的服務名稱一致 即 須要和scopename 一致

註釋部分 錯誤會形成網關轉發跳轉出錯

 

測試demoAPI無需改動

 

測試步驟:

1.token獲取 

post   

請求url: http://192.168.66.241:5000/auth/login

參數 :

grant_type:client_credentials
client_id:OcelotDemo
client_secret:123456

如圖:

2.測試訪問

get

url:192.168.66.241:5000/demo1/values

參數 :

Authorization:Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjRkMDRhNjk4OTZhMGNhYjZiY2Y4MjBiOTgyOTdlMjk2IiwidHlwIjoiSldUIn0.eyJuYmYiOjE1NDIzMzMwNzQsImV4cCI6MTU0MjMzNjY3NCwiaXNzIjoiaHR0cDovLzE5Mi4xNjguNjYuMjQxOjc1MDAiLCJhdWQiOlsiaHR0cDovLzE5Mi4xNjguNjYuMjQxOjc1MDAvcmVzb3VyY2VzIiwiZGVtb0FQaSJdLCJjbGllbnRfaWQiOiJPY2Vsb3REZW1vIiwic2NvcGUiOlsiZGVtb0FQaSJdfQ.frqi9W3Yt2XpKStaxLWprVwaer1AB0eeXRdXoGxUBa0IAH-6kzjXKKxznTx-DvEiitZXuF9QBetcbe-otHFG0sHWhQstbD-m8GOHjp8C1RqQ1QFDjO6VspgMEjtugeiOuG2CibStySMZiWl4FpftMsijh9Qzi7RJn6DeHNChLXuv0R2XxCvJa0Bx2hUkRt8yH2pxhrFr4XpxKmtjlks2saPWIrN3D3JWYYcILMcQK-1GDRgc7v-q-KwnCL3DWWdF1kLDeaKv2VgLvnofwfUGQZ2fqZv91t0K0meoWUR3mxPo3JpoO5PnWI0-bttBcoKEC__k3ZgcoKUtPhtgUfcIeA
Content-Type:application/json

如圖:

 

 

 

再次引用參考連接:

微服務系列教程

https://www.cnblogs.com/edisonchou/p/dotnetcore_microservice_foundation_blogs_index_final.html

相關文章
相關標籤/搜索