IdentityServer4 4.x版本 配置Scope的正确姿势
點(diǎn)擊上方藍(lán)字"小黑在哪里"關(guān)注我吧
前言
IdentityServer4 是為ASP.NET Core系列量身打造的一款基于 OpenID Connect 和 OAuth 2.0 認(rèn)證的框架
IdentityServer4官方文檔:https://identityserver4.readthedocs.io/
看這篇文章前默認(rèn)你對(duì)IdentityServer4 已經(jīng)有一些了解。
本篇使用IdentityServer4的4.x版本,跟老版本的稍微有些差別。下面直接進(jìn)入正題。
鑒權(quán)中心
創(chuàng)建IdentityServer4項(xiàng)目
使用IdentityServer4 來搭建一個(gè)鑒權(quán)中心,首先建議安裝一下IdentityServer4的官方項(xiàng)目模板。也可以不安裝,自己創(chuàng)建項(xiàng)目,然后NuGet安裝需要的包也行。(不過還是推薦用官方的模板,很方便)。
命令行執(zhí)行:dotnet new -i IdentityServer4.Templates
image-20200629205619088安裝完成后會(huì)多出以下項(xiàng)目模板:
image-20200629205731577我這里選用is4inmem這個(gè)模板來創(chuàng)建項(xiàng)目,這個(gè)模板的數(shù)據(jù)都是寫死在內(nèi)存中的,并且包含了Quickstart頁面,比較簡單方便。
來到我的項(xiàng)目目錄下執(zhí)行:dotnet new is4inmem --name Idp
image-20200701190325246執(zhí)行完成會(huì)生成以下文件:
image-20200701195853822VS2019打開項(xiàng)目:
image-20200701195955107運(yùn)行項(xiàng)目:
image-20200701200225015配置ApiResource、ApiScope、Clients
修改Startup:
//?in-memory,?code?config builder.AddInMemoryIdentityResources(Config.IdentityResources); builder.AddInMemoryApiScopes(Config.ApiScopes); //添加API資源 builder.AddInMemoryApiResources(Config.ApiResources); builder.AddInMemoryClients(Config.Clients);這里比之前版本多了一個(gè)添加ApiScopes的方法:
builder.AddInMemoryApiScopes(Config.ApiScopes);
因?yàn)槲医酉聛碛幸Wo(hù)的API資源,所以需要添加一行:
builder.AddInMemoryApiResources(Config.ApiResources);
Config中的代碼:
public?static?class?Config {public?static?IEnumerable<IdentityResource>?IdentityResources?=>new?IdentityResource[]{new?IdentityResources.OpenId(),new?IdentityResources.Profile(),};public?static?IEnumerable<ApiScope>?ApiScopes?=>new?ApiScope[]{new?ApiScope("scope1"),//new?ApiScope("scope2"),};public?static?IEnumerable<ApiResource>?ApiResources?=>new?ApiResource[]{new?ApiResource("api1","#api1"){//!!!重要Scopes?=?{?"scope1"}},//new?ApiResource("api2","#api2")//{//????//!!!重要//????Scopes?=?{?"scope2"}//},};public?static?IEnumerable<Client>?Clients?=>new?Client[]{new?Client{ClientId?=?"postman?client",ClientName?=?"Client?Credentials?Client",AllowedGrantTypes?=?GrantTypes.ClientCredentials,ClientSecrets?=?{?new?Secret("postman?secret".Sha256())?},AllowedScopes?=?{?"scope1"?}},}; }我添加了一個(gè)ID為postman client的客戶端,授權(quán)模式就用最簡單的ClientCredentials客戶端模式。需要注意的是4.x版本的ApiScope和ApiResource是分開配置的,然后在ApiResource中一定要添加Scopes。如果你在網(wǎng)上搜的IdentityServer4教程比較老的,都是沒有這個(gè)ApiScope的,默認(rèn)ApiResource的Name作為Scope。類似這樣:
public?static?IEnumerable<ApiResource>?ApiResources?=>new?ApiResource[]{new?ApiResource("api1","#api1"),//錯(cuò)誤new?ApiResource("api2","#api2"),//錯(cuò)誤};public?static?IEnumerable<Client>?Clients?=>new?Client[]{new?Client{......AllowedScopes?=?{?"api1",?"api2"?}},};如果你這么寫的話,雖然不影響你獲取token,但是你訪問api資源的話,永遠(yuǎn)會(huì)得到一個(gè)401錯(cuò)誤!!!
ApiResource
下面添加一個(gè)api1資源,新建asp.netcore web應(yīng)用并使用webapi模板:
image-20200701211036365NuGet安裝:Microsoft.AspNetCore.Authentication.JwtBearer
Startup部分代碼:
public?void?ConfigureServices(IServiceCollection?services) {services.AddControllers();services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options?=>{//IdentityServer地址options.Authority?=?"http://localhost:5001";//對(duì)應(yīng)Idp中ApiResource的Nameoptions.Audience?=?"api1";//不使用httpsoptions.RequireHttpsMetadata?=?false;}); }//?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.UseHttpsRedirection();app.UseRouting();//身份驗(yàn)證app.UseAuthentication();//授權(quán)app.UseAuthorization();app.UseEndpoints(endpoints?=>{endpoints.MapControllers();}); }給WeatherForecastController添加[Authorize]標(biāo)記:
image-20200701214601854運(yùn)行Api1Resource,用postman測試訪問weatherforecast接口:
image-20200701214742071此時(shí)得到401錯(cuò)誤。下面先去Idp獲取一個(gè)token:
image-20200701215031535拿到token后再去訪問weatherforecast就沒問題了:
image-20200701215748634進(jìn)行到這里,好像跟scope都沒什么關(guān)系,那么scope到底有什么用處呢?
ApiScope策略授權(quán)
繼續(xù)修改代碼。
Api1Resource項(xiàng)目NuGet安裝:IdentityServer4.AccessTokenValidation
image-20200701221017612再新建一個(gè)TestController用于區(qū)分:
image-20200701223359517下面我需要做的是使用scope結(jié)合策略授權(quán)來分別限制TestController和WeatherForecastController的訪問權(quán)限。
修改Startup:
public?void?ConfigureServices(IServiceCollection?services) {......services.AddAuthorization(options?=>{//基于策略授權(quán)options.AddPolicy("WeatherPolicy",?builder?=>{//客戶端Scope中包含api1.weather.scope才能訪問builder.RequireScope("api1.weather.scope");});//基于策略授權(quán)options.AddPolicy("TestPolicy",?builder?=>{//客戶端Scope中包含api1.test.scope才能訪問builder.RequireScope("api1.test.scope");});}); }為了好理解,我把scope名稱分別改成了:api1.weather.scope和api1.test.scope。
WeatherForecastController的Authorize標(biāo)記修改一下:[Authorize(Policy = "WeatherPolicy")]
TestController的代碼很簡單:
image-20200701224046637因?yàn)樾薷牧藄cope名稱,需要把Idp中的scope名稱也改一下:
public?static?IEnumerable<ApiScope>?ApiScopes?=>new?ApiScope[]{new?ApiScope("api1.weather.scope"),new?ApiScope("api1.test.scope"),//new?ApiScope("scope2"),};public?static?IEnumerable<ApiResource>?ApiResources?=>new?ApiResource[]{new?ApiResource("api1","#api1"){//!!!重要Scopes?=?{?"api1.weather.scope",?"api1.test.scope"?}},//new?ApiResource("api2","#api2")//{//????//!!!重要//????Scopes?=?{?"scope2"}//},};客戶端定義,AllowedScopes暫時(shí)只給一個(gè)api1.weather.scope測試一下
public?static?IEnumerable<Client>?Clients?=>new?Client[]{new?Client{ClientId?=?"postman?client",ClientName?=?"Client?Credentials?Client",AllowedGrantTypes?=?GrantTypes.ClientCredentials,ClientSecrets?=?{?new?Secret("postman?secret".Sha256())?},AllowedScopes?=?{?"api1.weather.scope"?}},};postman獲取token:
image-20200701225242813訪問weatherforecast接口,正常響應(yīng)200。
image-20200701225430395再訪問test,得到403錯(cuò)誤:
image-20200701225508071接下來修改一下Idp的客戶端定義,添加api1.test.scope:
AllowedScopes = { "api1.weather.scope", "api1.test.scope" }
修改Idp后一定要重新獲取token,jwt就是這樣,一旦生成就無法改變。
image-20200701230022811拿到新的token后訪問test和weatherforecast,這時(shí)候就都可以正常響應(yīng)了。
image-20200701230107290image-20200701230209695總結(jié)
以上使用IdentityServer4搭建了一個(gè)鑒權(quán)中心,保護(hù)API資源,并使用ApiScope配合策略授權(quán)完成了一個(gè)簡單的權(quán)限控制。IdentityServer4的玩法非常多,知識(shí)點(diǎn)也很多。強(qiáng)烈推薦B站的@solenovex 楊老師的視頻,地址:https://www.bilibili.com/video/BV16b411k7yM 多看幾遍,會(huì)有收獲。。。
需要代碼的點(diǎn)這里:https://github.com/xiajingren/IdentityServer4-4.x-Scope-Demo
- END -如果本文對(duì)您有用,
不妨點(diǎn)個(gè)“在看”或者轉(zhuǎn)發(fā)朋友圈支持一下
總結(jié)
以上是生活随笔為你收集整理的IdentityServer4 4.x版本 配置Scope的正确姿势的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 五分钟快速搭建Serverless免费邮
- 下一篇: 如何基于 DDD 构建微服务?