1. 程式人生 > >ASP.NET CORE API Swagger+IdentityServer4授權驗證

ASP.NET CORE API Swagger+IdentityServer4授權驗證

簡介

本來不想寫這篇博文,但在網上找到的文章部落格都沒有完整配置資訊,所以這裡記錄下。

不瞭解IdentityServer4的可以看看我之前寫的入門博文

Swagger 官方演示地址

原始碼地址

配置IdentityServer4服務端

首先建立一個新的ASP.NET Core專案。

 

這裡選擇空白項,新建空白專案

等待建立完成後,右鍵單擊專案中的依賴項選擇管理NuGet程式包,搜尋IdentityServer4並安裝:

等待安裝完成後,下載官方提供的UI檔案,並拖放到專案中。下載地址:https://github.com/IdentityServer/IdentityServer4.Quickstart.UI

配置IdentityServer4

在專案中新建檔案Config.cs檔案,原始碼如下:

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

namespace IdentityServer
{
    public static class Config
    {
        
public static IEnumerable<IdentityResource> GetIdentityResources() { return new IdentityResource[] { new IdentityResources.OpenId(), new IdentityResources.Profile(), }; } /// <summary> /// API資訊
/// </summary> /// <returns></returns> public static IEnumerable<ApiResource> GetApis() { return new[] { new ApiResource("demo_api", "Demo API with Swagger") }; } /// <summary> /// 客服端資訊 /// </summary> /// <returns></returns> public static IEnumerable<Client> GetClients() { return new[] { new Client { ClientId = "demo_api_swagger",//客服端名稱 ClientName = "Swagger UI for demo_api",//描述 AllowedGrantTypes = GrantTypes.Implicit,//指定允許的授權型別(AuthorizationCode,Implicit,Hybrid,ResourceOwner,ClientCredentials的合法組合)。 AllowAccessTokensViaBrowser = true,//是否通過瀏覽器為此客戶端傳輸訪問令牌 RedirectUris = { "http://localhost:5001/swagger/oauth2-redirect.html" }, AllowedScopes = { "demo_api" }//指定客戶端請求的api作用域。 如果為空,則客戶端無法訪問 } }; } } }

開啟Startup.cs檔案配置,修改如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Quickstart.UI;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;

namespace IdentityServer
{
    public class Startup
    {
        // 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)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            //配置身份伺服器與記憶體中的儲存,金鑰,客戶端和資源
            services.AddIdentityServer()
                   .AddDeveloperSigningCredential()
                   .AddInMemoryApiResources(Config.GetApis())//新增api資源
                   .AddInMemoryClients(Config.GetClients())//新增客戶端
                   .AddInMemoryIdentityResources(Config.GetIdentityResources())//新增對OpenID Connect的支援
                   .AddTestUsers(TestUsers.Users); //新增測試使用者
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            //IdentityServe
            app.UseIdentityServer();
            //新增靜態資源訪問
            app.UseStaticFiles();
            //
            app.UseMvcWithDefaultRoute();
        }
    }
}

修改啟動埠為5000,啟動訪問:http://localhost:5000/,效果如下:

API配置

新建ASP.NET CORE API專案,使用NuGet新增包:IdentityServer4.AccessTokenValidation、Swashbuckle.AspNetCore

在API中新增 AuthorizeCheckOperationFilter用於管理IdentityServer4認證處理,程式碼如下:

using Microsoft.AspNetCore.Authorization;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace TPL.API
{
    /// <summary>
    /// IdentityServer4認證過濾器
    /// </summary>
    public class AuthorizeCheckOperationFilter : IOperationFilter
    {
        public void Apply(Operation operation, OperationFilterContext context)
        {
            //獲取是否新增登入特性
            var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
             .Union(context.MethodInfo.GetCustomAttributes(true))
             .OfType<AuthorizeAttribute>().Any();

            if (authAttributes)
            {
                operation.Responses.Add("401", new Response { Description = "暫無訪問許可權" });
                operation.Responses.Add("403", new Response { Description = "禁止訪問" });
                //給api新增鎖的標註
                operation.Security = new List<IDictionary<string, IEnumerable<string>>>
                {
                    new Dictionary<string, IEnumerable<string>> {{"oauth2", new[] {"demo_api"}}}
                };
            }
        }
    }
}

修改API的Startup檔案,修改如下:

using System;
using System.Collections.Generic;
using IdentityServer4.AccessTokenValidation;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.Swagger;

namespace TPL.API
{
    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.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            //使用者校驗
            services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
              .AddIdentityServerAuthentication(options =>
              {
                  options.Authority = "http://localhost:5000"; // IdentityServer伺服器地址
                  options.ApiName = "demo_api"; // 用於針對進行身份驗證的API資源的名稱
                  options.RequireHttpsMetadata = false; // 指定是否為HTTPS
              });
            //新增Swagger.
            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new Info { Title = "Protected API", Version = "v1" });
                //向生成的Swagger新增一個或多個“securityDefinitions”,用於API的登入校驗
                options.AddSecurityDefinition("oauth2", new OAuth2Scheme
                {
                    Flow = "implicit", // 只需通過瀏覽器獲取令牌(適用於swagger)
                    AuthorizationUrl = "http://localhost:5000/connect/authorize",//獲取登入授權介面
                    Scopes = new Dictionary<string, string> {
                        { "demo_api", "Demo API - full access" }//指定客戶端請求的api作用域。 如果為空,則客戶端無法訪問
                    }
                });

                options.OperationFilter<AuthorizeCheckOperationFilter>(); // 新增IdentityServer4認證過濾
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseAuthentication();

            // Swagger JSON Doc
            app.UseSwagger();

            // Swagger UI
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
                options.OAuthClientId("demo_api_swagger");//客服端名稱
                options.OAuthAppName("Demo API - Swagger-演示"); // 描述
            });
            app.UseMvc();
        }
    }
}

修改Properties資料夾下的launchSettings啟動埠為5001,這裡埠必須跟IdentityServer4中的Config配置的客服端資源中保持一致。

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false, 
    "anonymousAuthentication": true, 
    "iisExpress": {
      "applicationUrl": "http://localhost:5001",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "TPL.API": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "applicationUrl": "http://localhost:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

訪問呈現效果如下,從中效果圖中可以看出新增登入按鈕,API控制器中如果新增Authorize特性,對應介面會有一把鎖的標誌:

如果未授權訪問介面返回401,未授權提示:

點選Authorize按鈕會跳轉到IdentityServer4登入頁面,登入授權成功後會自動獲取登入後伺服器返回Token,再次訪問介面即可正常訪問,授權前後效果如下:

到此演示專案完畢。如果需求配合自己的資料庫使用請看我前面寫過的博文 自定義登入即可。