ASP.NET Core的身份認證框架IdentityServer4--(5)自定義用戶登錄(使用官網提供的UI)


IdentityServer官方提供web頁面,可以根據需求修改樣式。具體UI下載跟配置參考官網文檔。

文檔地址:https://identityserver4.readthedocs.io/en/release/quickstarts/3_interactive_login.html

使用UI登錄涉及的知識點參考園里大佬@solenovex的文章。這里不在重復說明,感興趣的同學可以去看看。原文地址:https://www.cnblogs.com/cgzl/p/9253667.html

我這里是根據官方提供的UI進行修改、自定義用戶登錄、訪問API。

源碼地址:https://github.com/YANGKANG01/IdentityServer4-IdentityAuth

一、配置IdentityServer

1、引入官網包:IdentityServer4

2、需要重新定義Web端信息,除了ClientId,AllowedGrantTypes,ClientSecrets,AllowedScopes等屬性還需要配置登錄成功或注銷后的返回地址RedirectUrisPostLogoutRedirectUrisConfig文件配置如下:

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

namespace IdentityServer
{
    /// <summary>
    /// IdentityServer配置
    /// </summary>
    public class Config
    {
        /// <summary>
        /// 添加對OpenID Connect的支持
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(), //必須要添加,否則報無效的scope錯誤
                new IdentityResources.Profile()
            };
        }
        /// <summary>
        /// 定義系統中的API資源
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("api1", "My API")
            };
        }

        /// <summary>
        /// 客戶端訪問資源
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Client> GetClients()
        {
            // 客戶端信息
            return new List<Client>
            {
             //自定義接口登錄的客戶端
             new Client
                {
                    //客戶端ID名稱
                    ClientId = "client1",
                    //客戶端訪問方式:密碼驗證
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                    //用於認證的密碼加密方式
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    //客戶端有權訪問的范圍
                    AllowedScopes = { "api1",
                    IdentityServerConstants.StandardScopes.OpenId, //必須要添加,否則報403 forbidden錯誤
                    IdentityServerConstants.StandardScopes.Profile
                 }
                },
                //定義mvc客戶端
                new Client
                {
                    //客戶端ID名稱
                    ClientId = "mvc",
                    ClientName = "MVC Client",
                    //訪問類型
                    AllowedGrantTypes = GrantTypes.Hybrid,
                    //關閉確認是否返回身份信息界面
                    RequireConsent=false,
                   // 登錄成功后重定向地址
                    RedirectUris = { "http://localhost:5002/signin-oidc" },
                   //注銷成功后的重定向地址
                    PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
                     //用於認證的密碼加密方式
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                     //客戶端有權訪問的范圍
                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "api1",//要訪問的api名稱
                    },
                }
            };
        }
    }
}

3、Startup的配置跟前面自定義接口登錄一樣沒什么變化,這里也貼下源碼方便沒看前篇的同學:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer.Service;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
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.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())//用戶信息建模
                .AddInMemoryApiResources(Config.GetApiResources())//添加api資源
                .AddInMemoryClients(Config.GetClients())//添加客戶端
                .AddResourceOwnerValidator<LoginValidator>()//用戶校驗
                .AddProfileService<ProfileService>();
            //注冊mvc服務
            services.AddMvc();
        }

        // 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();
            }
            //添加到HTTP管道中。
            app.UseIdentityServer();
            //添加靜態資源訪問
            app.UseStaticFiles();
            //添加mvc到管道中
            app.UseMvcWithDefaultRoute();

        }
    }
}

 4、添加官網UI后找到AccountController類,修改登錄方法Login ,把下圖中的代碼替換成自己的查詢數據庫用戶即可,這里官方使用的是TestUsers類中自定義的用戶來登錄。

二、Web端配置獲取登錄后的用戶信息

1、引入官網包:IdentityModel

2、Startup配置如下。ResponseType返回類型詳情可參考@solenovex的文章,大佬在文章說的比較詳細,這里不在重復說明,地址:https://www.cnblogs.com/cgzl/p/9253667.html

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Web
{
    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.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
                .AddCookie("Cookies")
                .AddOpenIdConnect("oidc", options =>
                {
                    options.SignInScheme = "Cookies";
                    //授權端服務地址
                    options.Authority = "http://localhost:5000/";
                    //是否https請求
                    options.RequireHttpsMetadata = false;
                    //客戶端ID名稱
                    options.ClientId = "mvc";
                    options.ClientSecret = "secret";
                    //返回的類型
                    options.ResponseType = "code id_token";
                    //添加自定義用戶信息
                    options.Scope.Clear();
                    options.Scope.Add("openid");
                    options.Scope.Add("profile");
                    //是否存儲token
                    options.SaveTokens = true;
                    //用於設置在從令牌端點接收的id_token創建標識后,處理程序是否應轉到用戶信息端點
                    options.GetClaimsFromUserInfoEndpoint = true;
                    //訪問名稱api
                    options.Scope.Add("api1");
                    //避免claims被默認過濾掉,如果不想讓中間件過濾掉nbf和amr, 把nbf和amr從被過濾掉集合里移除。可以使用下面這個方方式:
                    options.ClaimActions.Remove("nbf");
                    options.ClaimActions.Remove("amr");
                    //刪除某些Claims
                    options.ClaimActions.DeleteClaim("sid");
                    options.ClaimActions.DeleteClaim("idp");
                });

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // 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();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseCookiePolicy();
            //添加用戶驗證中間件
            app.UseAuthentication();
            //
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

 3、在需要登錄的頁面方法添加Authorize特性。

 啟動web 會看到頁面自動重定向到登錄頁面效果如圖:

 4、獲取用戶信息可使用HttpContext.User.Identity來獲取當前用戶信息,代碼如下:

 //獲取用戶信息
 var claimIdentity = (ClaimsIdentity)HttpContext.User.Identity;
 var claimsPrincipal = claimIdentity.Claims as List<Claim>;

5、獲取用戶token,這里的token是服務端生成發送給客戶端,用於身份校驗,可使用token訪問需要登錄權限的API接口。代碼如下:

//獲取用戶token
var token = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);

Ps:注銷登錄默認跳轉到退出信息提示頁面,如不需要修改服務端的 AccountOptions類中的AutomaticRedirectAfterSignOut屬性,默認為false,修改為true即可。

三、API配置

1、引入官網包:IdentityServer4.AccessTokenValidation

2、Startup類配置如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace 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.AddMvcCore()
                    .AddAuthorization()//添加身份驗證服務
                    .AddJsonFormatters();
            //AddAuthentication將身份驗證服務添加到DI並配置"Bearer"為默認方案
            services.AddAuthentication("Bearer")
                    .AddIdentityServerAuthentication(options =>
                    {
                        options.Authority = "http://localhost:5000";//identifyServer服務地址
                        options.RequireHttpsMetadata = false;//是否使用https

                        options.ApiName = "api1";//進行身份驗證的API資源的名稱
                    });
        }

        // 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();

            app.UseMvc();
        }
    }
}

3、給對應的API接口添加Authorize特性,Web端登錄通過token訪問該接口。代碼如下:

//獲取用戶token
var token = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
//實例化HttpClient
var client = new HttpClient();
client.SetBearerToken(token);
//請求identity接口
var response = await client.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
{
     Console.WriteLine(response.StatusCode);
}

 


免責聲明!

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



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