IdentityServer4 4.x版本 配置Scope的正确姿势
前言
IdentityServer4 是为ASP.NET Core系列量身打造的一款基于 OpenID Connect 和 OAuth 2.0 认证的框架
IdentityServer4官方文档:https://identityserver4.readthedocs.io/
看这篇文章前默认你对IdentityServer4 已经有一些了解。
本篇使用IdentityServer4的4.x版本,跟老版本的稍微有些差别。下面直接进入正题。
鉴权中心
创建IdentityServer4项目
使用IdentityServer4 来搭建一个鉴权中心,首先建议安装一下IdentityServer4的官方项目模板。也可以不安装,自己创建项目,然后NuGet安装需要的包也行。(不过还是推荐用官方的模板,很方便)。
命令行执行:dotnet new -i IdentityServer4.Templates

安装完成后会多出以下项目模板:

我这里选用is4inmem这个模板来创建项目,这个模板的数据都是写死在内存中的,并且包含了Quickstart页面,比较简单方便。
来到我的项目目录下执行:dotnet new is4inmem --name Idp

执行完成会生成以下文件:

VS2019打开项目:

运行项目:

配置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);
这里比之前版本多了一个添加ApiScopes的方法:
builder.AddInMemoryApiScopes(Config.ApiScopes);
因为我接下来有要保护的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" }
},
};
}
我添加了一个ID为postman client的客户端,授权模式就用最简单的ClientCredentials客户端模式。需要注意的是4.x版本的ApiScope和ApiResource是分开配置的,然后在ApiResource中一定要添加Scopes。如果你在网上搜的IdentityServer4教程比较老的,都是没有这个ApiScope的,默认ApiResource的Name作为Scope。类似这样:
public static IEnumerable<ApiResource> ApiResources =>
new ApiResource[]
{
new ApiResource("api1","#api1"),//错误
new ApiResource("api2","#api2"),//错误
};
public static IEnumerable<Client> Clients =>
new Client[]
{
new Client
{
......
AllowedScopes = { "api1", "api2" }
},
};
如果你这么写的话,虽然不影响你获取token,但是你访问api资源的话,永远会得到一个401错误!!!
ApiResource
下面添加一个api1资源,新建asp.netcore web应用并使用webapi模板:

NuGet安装:Microsoft.AspNetCore.Authentication.JwtBearer
Startup部分代码:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
//IdentityServer地址
options.Authority = "http://localhost:5001";
//对应Idp中ApiResource的Name
options.Audience = "api1";
//不使用https
options.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();
//身份验证
app.UseAuthentication();
//授权
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
给WeatherForecastController添加[Authorize]标记:

运行Api1Resource,用postman测试访问weatherforecast接口:

此时得到401错误。下面先去Idp获取一个token:

拿到token后再去访问weatherforecast就没问题了:

进行到这里,好像跟scope都没什么关系,那么scope到底有什么用处呢?
ApiScope策略授权
继续修改代码。
Api1Resource项目NuGet安装:IdentityServer4.AccessTokenValidation

再新建一个TestController用于区分:

下面我需要做的是使用scope结合策略授权来分别限制TestController和WeatherForecastController的访问权限。
修改Startup:
public void ConfigureServices(IServiceCollection services)
{
......
services.AddAuthorization(options =>
{
//基于策略授权
options.AddPolicy("WeatherPolicy", builder =>
{
//客户端Scope中包含api1.weather.scope才能访问
builder.RequireScope("api1.weather.scope");
});
//基于策略授权
options.AddPolicy("TestPolicy", builder =>
{
//客户端Scope中包含api1.test.scope才能访问
builder.RequireScope("api1.test.scope");
});
});
}
为了好理解,我把scope名称分别改成了:api1.weather.scope和api1.test.scope。
WeatherForecastController的Authorize标记修改一下:[Authorize(Policy = "WeatherPolicy")]
TestController的代码很简单:

因为修改了scope名称,需要把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暂时只给一个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:

访问weatherforecast接口,正常响应200。

再访问test,得到403错误:

接下来修改一下Idp的客户端定义,添加api1.test.scope:
AllowedScopes = { "api1.weather.scope", "api1.test.scope" }
修改Idp后一定要重新获取token,jwt就是这样,一旦生成就无法改变。

拿到新的token后访问test和weatherforecast,这时候就都可以正常响应了。


总结
以上使用IdentityServer4搭建了一个鉴权中心,保护API资源,并使用ApiScope配合策略授权完成了一个简单的权限控制。IdentityServer4的玩法非常多,知识点也很多。强烈推荐B站的@solenovex 杨老师的视频,地址:https://www.bilibili.com/video/BV16b411k7yM 多看几遍,会有收获。。。
需要代码的点这里:https://github.com/xiajingren/IdentityServer4-4.x-Scope-Demo
IdentityServer4 4.x版本 配置Scope的正确姿势的更多相关文章
- iOS的多版本配置(版本分离,多环境配置)
前几天公司说一个客户要搞一个app,我说搞呗,跟我啥关系...他说,就是从咱的app上搞,什么都一样,就是一些logo啥的不一样.我一开始感觉,那就改改logo呗,后来一想,凑,百度推送,友盟统计,B ...
- 在Windows 7下面IIS7的安装和 配置ASP的正确方法
在Windows 7下如何安装IIS7,以及IIS7在安装过程中的一些需要注意的设置,以及在IIS7下配置ASP的正确方法. 一.进入Windows 7的 控制面板,选择左侧的打开或关闭Windows ...
- Eclipse(非J2EE版本)配置Extjs环境以及安装部署Tomcat
Eclipse(非J2EE版本)配置Extjs环境(Spket) 1. 安装spket插件,帮助->安装新软件->http://www.agpad.com/update. 2. 设置Spk ...
- Elasticsearch搜索引擎版本配置
简要描述: 搜索引擎版本配置 产品 版本号 ES版本要求 说明 PHP =5.5.38 Java =1.8.0_73 用于支持ES Elasticsearch =2.3.5 搜索引擎 ...
- 【MYSQL】mysql-5.6.19-win32免安装版本配置方法
[MYSQL]mysql-5.6.19-win32免安装版本配置方法 1.文件下载网站(http://dev.mysql.com/downloads/): 具体下载地址:http://211.136. ...
- XAMPP各个版本配置
XAMPP各个版本配置 http://code.stephenmorley.org/articles/xampp-version-history-apache-mysql-php/ XAMPP Ap ...
- Python在windows平台的多版本配置
Python在windows平台的多版本配置 快速阅读: python在windows平台的环境变量以及多版本配置 ,以及pycharm如何安装包,以及安装包出错时如何排查. 1.python环境 ...
- [ASP.NET Core 3框架揭秘] Options[1]: 配置选项的正确使用方式[上篇]
依赖注入不仅是支撑整个ASP.NET Core框架的基石,也是开发ASP.NET Core应用采用的基本编程模式,所以依赖注入十分重要.依赖注入使我们可以将依赖的功能定义成服务,最终以一种松耦合的形式 ...
- [ASP.NET Core 3框架揭秘] Options[2]: 配置选项的正确使用方式[下篇]
四.直接初始化Options对象 前面演示的几个实例具有一个共同的特征,即都采用配置系统来提供绑定Options对象的原始数据,实际上,Options框架具有一个完全独立的模型,可以称为Options ...
随机推荐
- Java实现冗余路径Redundant Paths
Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numb ...
- java实现第七届蓝桥杯压缩变换
压缩变换 压缩变换 小明最近在研究压缩算法. 他知道,压缩的时候如果能够使得数值很小,就能通过熵编码得到较高的压缩比. 然而,要使数值很小是一个挑战. 最近,小明需要压缩一些正整数的序列,这些序列的特 ...
- 终于我用JOL打破了你对java对象的所有想象
目录 简介 JOL简介 使用JOL分析VM信息 使用JOL分析String 使用JOL分析数组 使用JOL分析自动装箱 使用JOL分析引用关系 总结 简介 使用面向对象的编程语言的好处就是,虽然没有女 ...
- 彻底搞懂 etcd 系列文章(三):etcd 集群运维部署
0 专辑概述 etcd 是云原生架构中重要的基础组件,由 CNCF 孵化托管.etcd 在微服务和 Kubernates 集群中不仅可以作为服务注册与发现,还可以作为 key-value 存储的中间件 ...
- Error:org.gradle.api.internal.tasks.DefaultTaskInputs$TaskInputUnionFileCollection cannot be cast to...异常处理
这个是打开Android Studio项目报的错误提示,单纯从上面的提示还是不能太直接的知道什么问题.后来我想这个项目的Gradle版本与我当前AS使用的版本不一致,可能是这个问题. 修改build. ...
- Go语言json编码驼峰转下划线、下划线转驼峰
目录 一.需求 二.实现 三.使用 JsonSnakeCase统一转下划线json JsonSnakeCase统一转驼峰json 一.需求 golang默认的结构体json转码出来,都是大写驼峰的,并 ...
- 使用PyQtGraph绘制数据滚动图形(3)
import pyqtgraph as pg import numpy as np from pyqtgraph.Qt import QtGui, QtCore app = pg.QtGui.QApp ...
- Python 报错:NameError: name 'ctypes' is not defined
使用python中的ctypes模块可以很方便的调用windows的dll(也包括linux下的so等文件) 引入ctypes库 有两种方法 from ctypes import * import c ...
- 手写网页扫雷之js部分(vue)
var vm = new Vue({ el:"#ui", data(){ return{ num:0, saoleiStyle:{ width: "0px", ...
- CDN百科第四讲 | 如何优雅地在云上“摆摊”——做直播带货,你不得不关注的技术
最近,国家政策开始鼓励“地摊经济”,一时间各家企业平台纷纷推出地摊扶持政策,地摊概念股顺势大涨,地摊生态及配套商品也开始走俏,甚至在网络上也涌现出各种“新摊主速成攻略”,万亿的烟火经济俨然已经走上风口 ...