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
等屬性還需要配置登錄成功或注銷后的返回地址RedirectUris
跟PostLogoutRedirectUris
。Config
文件配置如下:
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); }