ASP.NET Core3.1使用Identity Server4建立Authorization Server-2

前言

建立Web Api項目

在同一個解決方案下建立一個Web Api項目IdentityServer4.WebApi,然後修改Web Api的launchSettings.json。參考第一節,當然可以不修改的,端口號為5001

{ 
  "profiles": { 
    "IdentityServer4.WebApi": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "//localhost:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

添加Swagger幫助頁面

官方文檔://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?tabs=visual-studio&view=aspnetcore-3.1

Startup.ConfigureServices方法中將Swagger生成器添加到服務集合:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            // Register the Swagger generator, defining one or more Swagger documents
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
            });
        }

OpenApiInfo需要 using Microsoft.OpenApi.Models;

在該Startup.Configure方法中,啟用用於提供生成的JSON文檔和Swagger UI的中間件:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger();
            // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
            // specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            });


            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

把Web Api設為啟動項目,打開://localhost:5001/swagger/index.html訪問Swagger幫助頁面:

如果要在應用程序的根目錄(//localhost:<port>/)提供Swagger UI ,請將RoutePrefix屬性設置為空字符串:

app.UseSwaggerUI(c =>
{
 c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
 c.RoutePrefix = string.Empty;
});

順便我們把launchSettings.json"launchUrl": "weatherforecast",刪掉,這個是在瀏覽器中啟動的默認URL。然後我們再次啟動,就可以直接看到Swagger的幫助頁面了。

添加庫IdentityServer4.AccessTokenValidation

Web Api配置Identity Server就需要對token進行驗證, 這個庫就是對access token進行驗證的. 通過NuGet安裝:

在Startup的ConfigureServices裏面註冊配置:

官方文檔的配置:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

        services.AddAuthentication("Bearer")
            .AddJwtBearer("Bearer", options =>
            {
                options.Authority = "//localhost:5001";

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = false
                };
            });
    }

官方文檔的這個配置是不進行驗證Api的Scope和其他一些配置的,也就是只要我拿到Access Token就可以訪問了。但實際情況應該是我們可能存在多個api項目,有些只能訪問api1、有些只能訪問api2。

我們的配置,完整的Web Api Startup.cs

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;

namespace IdentityServer4.WebApi
{
    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.AddControllers();

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false; 
                options.Authority = "//localhost:5000"; 
                 options.Audience = "api1"; 
            });

            // Register the Swagger generator, defining one or more Swagger documents
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
            });
        }

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

            //身份驗證
            app.UseAuthentication();

            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger();
            // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
            // specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
                c.RoutePrefix = string.Empty;
            });


            app.UseRouting();

            //授權
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

AddAuthentication:將身份驗證服務添加到DI並配置Bearer為默認方案。

UseAuthentication 將身份驗證中間件添加到管道中,以便對主機的每次調用都將自動執行身份驗證。

UseAuthorization 添加了授權中間件,以確保匿名客戶端無法訪問我們的API端點。

添加[Authorize]屬性:

打開WeatherForecastController, 在Controller上面添加這個屬性:

然後我們打開://localhost:5001/weatherforecast

401意思是未授權

HTTP狀態碼://www.runoob.com/http/http-status-codes.html

所以我們首先需要獲取到一個token。那就需要把上一節的Authorization Server也跑起來。解決方案右鍵,啟動項目設置為多個啟動項目,AuthServer項目放前面。

然後運行, 使用Postman先獲取token:

然後複製一下 access_token的值。新建一個Web Api項目的請求, 把access_token貼到Authorization選擇TYPE為Bearer Token的Token里去。

然後,我們就看到請求成功啦~。

驗證下範圍

還記得我們Web Api的Startup.cs中配置的當前Api為api1,他是和我們AuthServer項目的配置統一的,現在我們改為api2試一下,找一個不存在的,驗證下是否還能訪問Api接口。

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false; 
                options.Authority = "//localhost:5000"; 
                options.Audience = "api2"; 
            });

重新運行項目,獲取token,訪問api

可以看到,token是可以正常獲取的,但是我們不能訪問api了。

分析一下Token

去//jwt.io/ 可以分析一下這個token,感興趣的可以自己了解下,這塊資料很多的還是。

End

雖然系列內容基本是參考楊旭老師的,但是真的寫起來還是滿費力氣的,在這裡謝謝楊老師,另外B站有楊老師完整版的Identity Server4視頻,大家可以去看下哦~

推廣下自己的公眾號一個逗逼的程序員,主要記錄自己工作中解決問題的思路分享及學習過程中的筆記。絕對不會程序員販賣程序員的焦慮來割韭菜