ASP.NET Core 2はJwtテクノロジーを利用してサービス側でクライアントのアイデンティティ認証を実現

7690 ワード

背景
マイクロサービスアーキテクチャでは、システム全体を異なるビジネスまたは機能によって異なる独立したサブシステムに分割し、REST APIまたはRPCを介して通信し、相互に呼び出し、各サブシステム間の直列構造を形成するのが一般的である.ここでは,REST APIの通信方式を採用する.
例:
1、「ユーザーセンター」の独立したサブシステム名「Lezhima.UserHub」があり、ASPに基づくものである.NET Core mvc 2.0のプロジェクト.
2、ユーザーの注文を処理する独立したサブシステム名は「Lezhima.UserOrder」であり、ASPに基づくものである.NET Core webp api 2.0のプロジェクト.
3、同時にユーザーファイルのアップロードを処理する独立したサブシステム名は「Lezhima.UserUpload」であり、ASPに基づくものである.NET Core webp api 2.0のプロジェクト.
ビジネス関係は次のとおりです.
ユーザーが正常にログインした後に“Lezhima.UserHub”に入って、ユーザーが注文を見る時フロントエンドAjaxを通じて“Lezhima.UserOrder”のweb apiインターフェースを呼び出して、ユーザーがピクチャーをアップロードするのはフロントエンドAjaxを通じて“Lezhima.UserUpload”のweb apiインターフェースを呼び出します.
これで、私たちは上記の業務関係を理解した後、心の中で必ず次の2つの問題が発生します.
1、「Lezhima.UserOrder」と「Lezhima.UserUpload」の2つの独立したシステム内のweb apiインタフェースのセキュリティをどのように保障するか.
2、「Lezhima.UserHub」ステーションでTokenを発行する方法.
では、質問を持ってASPと結びつけます.NET Coreが持っているJwtテクノロジーで具体的な実装について議論します(賢いあなたはもっと良い解決方法があるかもしれませんが、ぜひ教えてください.ありがとうございます).
Jwtフルネーム:JSON Web Tokenは、成熟した技術であり、園子にもこの方面の知識がたくさんあるので、ここではもう繰り返しません.
 
実装の原理
「Lezhima.UserHub」局はログイン検証を行っているので、一応信頼できると考えているので、フロントエンドAjaxが「Lezhima.UserOrder」局のweb apiインタフェースを要求するときに、まず自分のバックエンドに行ってTokenを生成し、それに伴って今回のクロスステーション要求と一緒に「Lezhima.UserOrder」局に持ち込み、「Lezhima.UserOrder」局は要求ヘッダのTokenが合法であるかどうかを検証し、合法であれば具体的な方法にルーティングを継続する.そうでなければリクエストを終了します.「Lezhima.UserUpload」ステーションの原理は「Lezhima.UserOrder」と同じです.
 
インプリメンテーションコード
Lezhima.UserHubはTokenコードを発行します.
        /// 
        ///           Token,         id    		
        /// 
        /// 
        /// 
        /// 
	  public static async Task GetAccessToken(string currentUserId,int expiresMinutes=2)
        {
            return await Task.Run(() =>
            {
				//    ,              				
                var secret = "NGUzNmNlNzQtZThkZC00YjRh";
				//   
                var iss = "Andre";
				//   
                var aud = "Andre";

                if (string.IsNullOrEmpty(secret) || string.IsNullOrEmpty(iss) || string.IsNullOrEmpty(aud))
                    return "";

                if (string.IsNullOrEmpty(currentUserId))
                    currentUserId = Guid.NewGuid().ToString();

                var now = DateTime.UtcNow;
                var claims = new Claim[]
                {
                    new Claim(JwtRegisteredClaimNames.Sub, currentUserId),
                    new Claim(JwtRegisteredClaimNames.Iat, now.ToUniversalTime().ToString(), ClaimValueTypes.Integer64)
                };
                var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret));
                var jwt = new JwtSecurityToken(
                       issuer: iss,
                       audience: aud,
                       claims: claims,
                       notBefore: now,
                       expires: now.Add(TimeSpan.FromMinutes(expiresMinutes)),
                       signingCredentials: new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)
                 );
                return new JwtSecurityTokenHandler().WriteToken(jwt);  //      token
            });           
        }

Lezhima.UserHubフロントエンドAjaxクロスステーション要求コード:
//    Ajax      
function GetWebDataByObject(url, requestMethon, paramter) {
    jQuery.support.cors = true;
    apiUrl = 'http://127.0.0.1:8012/';
    var token = GetToken(); //      Token  Web api   
    var result = [];
    $.ajax({
        type: requestMethon,
        url: apiUrl + url,
        data: paramter,
        async: false,
        beforeSend: function (xhr) {
			// Token       
            xhr.setRequestHeader("Authorization", "Bearer " + token);
        },  
        success: function (data) {
            result = data;
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            //    
            console.log(XMLHttpRequest.status);
            //   
            console.log(XMLHttpRequest.readyState);
            //        
            console.log(textStatus);
        }
    });
    return result;
}

「Lezhima.UserOrder」ステーションはJwtのToken検証を開始し、Startup.csには次のコードが追加されます.
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {            
            services.AddCors();
			
			//          、   、       
			//           Token   
            var audienceConfig = Configuration.GetSection("Audience");

            var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(audienceConfig["Secret"]));
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,
                ValidateIssuer = true,
                ValidIssuer = audienceConfig["Iss"],
                ValidateAudience = true,
                ValidAudience = audienceConfig["Aud"],
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero,
                RequireExpirationTime = true,
            };
			//  Jwt  
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options => {
                    options.RequireHttpsMetadata = false;
                    options.TokenValidationParameters = tokenValidationParameters;
                });

            services.AddMvc();


            var builder = new ContainerBuilder();
            builder.RegisterModule(new Evolution());
            builder.Populate(services);
            var container = builder.Build();
            return container.Resolve();
        }
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseCors(builder =>
              builder.WithOrigins("*")
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials()
            );         
            //    
            app.UseAuthentication();
            app.UseMvc();
        }

Lezhima.UserOrderのコントローラに認証フィルタ[Authorize]を追加します.次のコードがあります.
    [Route("api/[Controller]")]
    //      ,       Action    Token  
    [Authorize]
    public class OrderController : Controller
    {
        
    }

  
ここで、ASPに基づく.NET CoreのJwtクロスステーション検証Token案はすべて完成したので、簡単ではないでしょうか^^;  ^_^ !! 
 
まとめ
1、Token発行者と検証者は同じ秘密鍵を使用する必要があります.秘密鍵、発行者、受信者などのパラメータはプロファイルに配置して動的に構成することができます.
2、プロジェクトStartupクラスのConfigureServicesメソッドにJwt認証を使用する登録機能を追加する.
3、検証者プロジェクトのコントローラまたはメソッドにフィルタ[Authorize]を加えると認証がオンになります.
 
宣言
本文は作者のオリジナルで、転載して出典と原文の住所を保留して、ありがとうございます.文章があなたに助けをもたらすことができるならば、推薦あるいは関心を押して、あなたの支持に感謝します!