IdentityServer4:密碼模式

IdentityServer4:密碼授權模式

Api 資源項目

創建項目

打開 VS,創建一個“AspNet Core WebApi” 項目, 名爲:Dotnet.WebApi.Ids4.ProductApi

依賴包

添加依賴包

    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.3" />

添加認證方案

修改 Program.cs 爲如下代碼:


using Microsoft.AspNetCore.Authentication.JwtBearer;
using System;

namespace Dotnet.WebApi.Ids4.ProductApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.Title = "ProductAPI服務器";

            var builder = WebApplication.CreateBuilder(args);

            builder.Services.AddControllers();

            builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    //IdentityServer4地址
                    options.Authority = "https://localhost:6001";
                    //認證的ApiResource名稱
                    options.Audience = "ProductAPIResource";
                    //使用JWT認證類型
                    options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
                });

            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();

            var app = builder.Build();

            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.Urls.Add("https://*:6012");

            app.UseHttpsRedirection();

            //身份驗證
            app.UseAuthentication();
            //授權
            app.UseAuthorization();

            app.MapControllers();

            app.Run();
        }
    }
}

其中:
(1)添加 JWT 認證:

            builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    //IdentityServer4地址
                    options.Authority = "https://localhost:6001";
                    //認證的ApiResource名稱
                    options.Audience = "CustomerAPIResource";
                    //使用JWT認證類型
                    options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
                });
 https://localhost:6001 是認證服務器地址。

添加 Api

新增文件:Controllers/ProductController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Dotnet.WebApi.Ids4.ProductApi.Controllers
{
    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class ProductController : ControllerBase
    {
        /// <summary>
        /// 添加產品
        /// </summary>
        /// <param name="product"></param>
        /// <returns></returns>
        [HttpPost("Add")]
        public ActionResult<string> Add(Product product)
        {
            var productId = product.Id;
            var productName = product.Name;
            //保存操作
            //........
            return $"productId:{productId}, productName:{productName}";
        }
    }
}

其中:
(1)在控制器上添加特性:[Authorize],這樣只有登錄用戶才能訪問,這樣就起到保護了Api資源的目的。

Product.cs

namespace Dotnet.WebApi.Ids4.PwdClient
{
    internal class Product
    {
        //唯一ID
        public int Id { get; set; }
        //產品名稱
        public string? Name { get; set; }
    }
}

認證服務器

創建項目

打開 VS,創建一個“AspNet Core 空” 項目,名爲:Dotnet.WebApi.Ids4.AuthService

依賴包

添加依賴包

<PackageReference Include="IdentityServer4" Version="4.1.2" />

配置 IdentityServer4

創建文件:IdentityConfig.cs,添加如下代碼:

using IdentityServer4.Models;
using IdentityServer4.Test;

namespace Dotnet.WebApi.Ids4.AuthService
{
    public static class IdentityConfig
    {
        /// <summary>
        /// 配置API作用域。
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<ApiScope> GetApiScopes()
        {
            return new List<ApiScope>
            {
                //產品相關API作用域
                new ApiScope("Product.Read","讀取產品信息。"),
                new ApiScope("Product.Add","添加產品信息。"),

                //共享API作用域
                new ApiScope("News","新聞信息。")
            };
        }

        /// <summary>
        /// 配置ApiResource。
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<ApiResource> GetApiResources()
        {
            //將多個具體的APIScope歸爲一個ApiResource。
            return new List<ApiResource>()
            {
                new ApiResource("ProductAPIResource","產品資源")
                {
                    Scopes={ "Product.Read", "Product.Add" ,"News" }
                }
            };
        }

        /// <summary>
        /// 配置客戶端應用。
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    //客戶端ID。
                    ClientId = "AppProductAddClient",
                    //密碼模式
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, 
                    //認證密鑰。
                    ClientSecrets =
                    {
                        new Secret("App00000002".Sha256())
                    },
                    //客戶端有權訪問的範圍。
                    AllowedScopes={ "Product.Add" }
                }
            };
        }

        /// <summary>
        /// 配置用戶。
        /// </summary>
        /// <returns></returns>
        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>()
            {
                new TestUser
                {
                    SubjectId="1",
                    Username="zhagnsan",
                    Password="123456"
                }
            };
        }
    }
}

密碼授權模式需要用戶輸入用戶名和密碼來換取 AccessToken, 故相較於客戶端模式,需做如下調整:
(1)Client的授權模式修改爲密碼模式;
IdentityConfig.cs

                new Client
                {
                    ......
                    //客戶端ID。
                    ClientId = "AppProductAddClient",
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, 
  
                }

(2)添加用戶

代碼清單;IdentityConfig.cs

        /// <summary>
        /// 配置用戶。
        /// </summary>
        /// <returns></returns>
        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>()
            {
                new TestUser
                {
                    SubjectId="1",
                    Username="zhagnsan",
                    Password="123456"
                }
            };
        }

然後在 Program.cs 中註冊 IdentityServer 時, 添加用戶

            //註冊IdentityServer4組件
            builder.Services.AddIdentityServer()
                ......
                .AddTestUsers(IdentityConfig.GetUsers())
             

集成 IdentityServer4

修改 Program.cs 爲如下代碼:

namespace Dotnet.WebApi.Ids4.AuthService
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.Title = "認證和授權服務器";

            var builder = WebApplication.CreateBuilder(args);

            //註冊IdentityServer4組件
            builder.Services.AddIdentityServer()
                .AddInMemoryApiScopes(IdentityConfig.GetApiScopes())
                .AddInMemoryApiResources(IdentityConfig.GetApiResources())
                .AddInMemoryClients(IdentityConfig.GetClients())
                .AddTestUsers(IdentityConfig.GetUsers())
                .AddDeveloperSigningCredential(); // 添加臨時內存中的證書

            var app = builder.Build();
            //修改端口號
            app.Urls.Add("https://*:6001");

            //添加IDS4中間件。
            //在瀏覽器中輸入如下地址訪問 IdentityServer4 的發現文檔:https://localhost:6001/.well-known/openid-configuration
            app.UseIdentityServer();

            app.Run();
        }
    }
}

其中,app.Urls.Add("https://*:6001"); 設置認證服務器的監聽端口爲:6001

密碼模式客戶端

創建項目

新控制檯項目,名爲:Dotnet.WebApi.Ids4.PwdClient

依賴包

添加依賴包

<PackageReference Include="IdentityServer4" Version="4.1.2" />

Program.cs

將 Program.cs 的代碼修改爲;

using static System.Runtime.InteropServices.JavaScript.JSType;

namespace Dotnet.WebApi.Ids4.PwdClient
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "密碼授權模式客戶端";

            Console.Write("請輸入用戶名:");
            var userName = Console.ReadLine();
            Console.Write("請輸入密碼:");
            var userPwd = Console.ReadLine();

            //獲取AccessToken
            var token = DataService.GetAccessToken(userName!, userPwd!).Result.AccessToken;
            Console.WriteLine(token);
            //操作API資源
            var result = DataService.AddAPIData(token);
            Console.WriteLine(result);

            Console.ReadKey();
        }
    }
}

DataService.cs

DataService 類 演示瞭如何從認證服務器獲取 AccessToken,然後向資源服務器發送請求獲取數據:

namespace Dotnet.WebApi.Ids4.PwdClient
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "密碼授權模式客戶端";

            Console.Write("請輸入用戶名:");
            var userName = Console.ReadLine();
            Console.Write("請輸入密碼:");
            var userPwd = Console.ReadLine();

            //獲取AccessToken
            var token = DataService.GetAccessToken(userName!, userPwd!).Result.AccessToken;
            Console.WriteLine(token);
            //操作API資源
            var result = DataService.AddAPIData(token);
            Console.WriteLine(result);

            Console.ReadKey();
        }
    }
}

運行成功後,需要用戶在控制檯終端中輸入用戶名和密碼來換取 AccessToken,然後才能獲取到受保護的Api數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章