IdentityServer4 保護.net framework webapi


一、IS4服務器配置

1、新建一個Asp.net  Core MVC程序,模板選擇 Empty 

2、Nuget添加 IdentityServer4,我這里添加的是2.5.3

3、添加Config文件,配置clients和scopes等信息,需要持久化配置的可以看 https://www.cnblogs.com/fengchao1000/p/10184921.html

public class Config
    {
        // scopes define the resources in your system
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile()
            };
        }

        public static IEnumerable<ApiResource> GetApis()
        {
            return new List<ApiResource>
            {
                new ApiResource("FrameworkAPI",new List<string>(){JwtClaimTypes.Subject})
            };
        }

        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            { 
                
                //Implicit模式Client配置,適用於SPA
                new Client
                {
                    ClientId = "Test",
                    ClientName = "Test",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,
                    AccessTokenLifetime = 60*60,
                    AccessTokenType = AccessTokenType.Jwt,
                    RedirectUris =
                    {
                        "https://localhost:5003/signin-callback.html",
                        "https://localhost:5003/silent-callback.html"
                    },
                    PostLogoutRedirectUris = { "https://localhost:5003" },
                    AllowedCorsOrigins = { "https://localhost:5003" },
                    RequireConsent = false,
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "FrameworkAPI"//對應webapi里面的scope配置
                    }
                },
                //ResourceOwnerPassword模式Client配置,適用於App、winform
                new Client
                {
                    ClientId = "App",
                    ClientName = "App",
                    ClientSecrets = { new Secret("123456".Sha256()) },
                    AccessTokenLifetime = 60*60,//單位s
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                    SlidingRefreshTokenLifetime =  2592000,
                    AllowOfflineAccess = true,
                    AllowedScopes = new List<string>
                    {
                        "FrameworkAPI",//對應webapi里面的scope配置
                        StandardScopes.OfflineAccess,
                        StandardScopes.OpenId,
                        StandardScopes.Profile
                    }
                }

            };
        }  
    }

4、添加ProfileService文件,用於自定義登錄返回信息

/// <summary>
    /// 自定義用戶登錄返回的信息claims
    /// </summary>
    public class ProfileService : IProfileService
    {
        private readonly ILogger logger;

        public ProfileService(ILogger<ProfileService> logger)
        {
            this.logger = logger;
        }

        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            try
            {
                var claims = context.Subject.Claims.ToList();

                context.IssuedClaims = claims.ToList();
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
        }

        public async Task IsActiveAsync(IsActiveContext context)
        {
            context.IsActive = true;
        }
    }

5、添加ResourceOwnerPasswordValidator文件,在ResourceOwnerPassword模式下用於自定義登錄驗證

/// <summary>
    ///ResourceOwnerPassword模式下用於自定義登錄驗證 
    /// </summary>
    public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        private readonly IConfiguration config;

        public ResourceOwnerPasswordValidator(IConfiguration config)
        {
            this.config = config;
        }

        public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            //根據context.UserName和context.Password與數據庫的數據做校驗,判斷是否合法
            if (context.UserName == "test" && context.Password == "test")
            {
                context.Result = new GrantValidationResult(
                 subject: context.UserName,
                 authenticationMethod: OidcConstants.AuthenticationMethods.Password);
            }
            else
            {
                //驗證失敗
                context.Result = new GrantValidationResult(
                    TokenRequestErrors.InvalidGrant,
                    "invalid custom credential"
                    );
            }
            return Task.FromResult(0);
        }
    }

6、在 Startup 配置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.AddIdentityServer()
                   //配置證書
                   .AddDeveloperSigningCredential()
                   //配置API資源
                   .AddInMemoryApiResources(Config.GetApis())
                   //配置身份資源
                   .AddInMemoryIdentityResources(Config.GetIdentityResources())
                   //預置Client
                   .AddInMemoryClients(Config.GetClients())
                   .AddProfileService<ProfileService>()
                   .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();

            services.AddAuthentication()
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = System.TimeSpan.FromMinutes(30);
                options.SlidingExpiration = true;
            });
        }

        // 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.UseIdentityServer();//IdentityServer4中間件
              
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("IdentityServer4");
            });
        }
    }

到這里我們IdentityServer4服務端已經搭建好了,我們用postman測試下,這里調用的是ResourceOwnerPassword模式

 二、.net framework webapi 配置

1、新建一個 .net framework webapi 程序

 \

2、由於webapi是.net Framework版本的,所以我們需要引用 IdentityServer3.AccessTokenValidation 作為api端token的驗證組件。

Nuget添加:

IdentityServer3.AccessTokenValidation    

IdentityModel   

Microsoft.Owin.Host.SystemWeb 

3、添加一個 Owin Startup.cs ,最好是用現有的startup類,而不要自己去新建一個類,然后修改名稱。

4、在Startup中配置 IdentityServer AccessToken 驗證參數

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        { 
            app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
            {
                Authority = "http://localhost:62527/",
                RequiredScopes = new[] { "FrameworkAPI" },//對應Client中配置的AllowedScopes和ApiResource

                DelayLoadMetadata = true
            });

        }
    }

5、在 WebAPIConfig 中加入 config.Filters.Add(new AuthorizeAttribute()) 來啟用授權驗證

config.Filters.Add(new AuthorizeAttribute());

 6、添加TestController

    public class TestController : ApiController 
    {  
        public IHttpActionResult Get()
        {  
            var user = User as ClaimsPrincipal;

            var claims = from c in user.Claims
                         select new
                         {
                             type = c.Type,
                             value = c.Value
                         };

            return Json(claims);
        }  
    }

最后項目結構如下:

 

三、測試

我們的服務端和webapi都已經配置好了,我們用postman測試下

1、直接訪問api地址 http://localhost:44387/test ,不加入token ,得到如下結果,返回401

 

 2、加入token ,驗證通過,返回200

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM