radmin提示授权码过期_IdentityServer4 客户端授权模式(Client Credentials)

(给DotNet加星标,提升.Net技能)

转自:朝闲cnblogs.com/Zing/p/13361386.html

前言

1、源码(.NET Core 2.2)

git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.git

2、相关章节

2.1、《IdentityServer4 (1) 客户端授权模式(Client Credentials)》

2.2、《IdentityServer4 (2) 密码授权(Resource Owner Password)》

2.3、《IdentityServer4 (3) 授权码模式(Authorization Code)》

2.4、《IdentityServer4 (4) 静默刷新(Implicit)》

2.5、《IdentityServer4 (5) 混合模式(Hybrid)》

3、参考资料

IdentityServer4 中文文档 http://www.identityserver.com.cn/

IdentityServer4 英文文档 https://identityserver4.readthedocs.io/en/latest/

4、流程图

客户端授权模式是最基本的使用场景,我们需要做一个API(受保护的资源),一个客户端(访问的应用),一个IdentityServer(用来授权)

92ee366534f6aaad6ca642a1afbe6cf5.png

一、创建IdentityServer

1、用VS创建一个Web 项目

97e2e70645a083fa36cffc5d4f583f0e.png

2、添加引用 IdentityServer4 包,下图是我已经安装好了的截图

a2c6d14190da993e36401f6f112d710f.png

3、添加一个配置文件(这里也可以使用json文件)

public class IdpConfig
{
///
/// 用户认证信息
///
///
public static IEnumerableGetApiResources(){
return new List
{new IdentityResources.OpenId(),new IdentityResources.Profile(),new IdentityResources.Address(),new IdentityResources.Email(),new IdentityResources.Phone()
};
}/// /// API 资源/// /// public static IEnumerableGetApis(){return new List
{new ApiResource("api1", "My API")
};
}/// /// 客户端应用/// /// public static IEnumerableGetClients(){return new List
{new Client
{// 客户端ID 这个很重要
ClientId = "client",//AccessToken 过期时间,默认3600秒,注意这里直接设置5秒过期是不管用的,解决方案继续看下面 API资源添加JWT//AccessTokenLifetime=5,// 没有交互性用户,使用 clientid/secret 实现认证。
AllowedGrantTypes = GrantTypes.ClientCredentials,// 用于认证的密码
ClientSecrets =
{new Secret("secret".Sha256())
},// 客户端有权访问的范围(Scopes)
AllowedScopes = { "api1" }
}
};
}
}

4、在StartUp.cs 里注册 IdentityServer4 

ConfigureServices()

services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddDeveloperSigningCredential()//解决Keyset is missing 错误
//.AddTestUsers(TestUsers.Users)
//.AddInMemoryIdentityResources(IdpConfig.GetApiResources())
.AddInMemoryApiResources(IdpConfig.GetApis())
.AddInMemoryClients(IdpConfig.GetClients());

Configure()方法添加使用 IdentityServer4 中间件

app.UseIdentityServer();

5、配置完成

启动项目,访问 http://localhost:5002/.well-known/openid-configuration (我的端口号是5002) ,可以浏览 发现文档,参考下图,说明已经配置成功。

后面客户端会使用里面的数据进行请求toke

项目第一次启动根目录也会生成一个文件 tempkey.rsa

85c6b84ebc38e1a61cbcb4da264c5fda.png

二、客户端

1、新建一个.Net Core Web 项目

这里可以使用其他建立客户端 。例如:控制台程序、wpf 等等。需要添加 NuGet 包 IdentityModel

dabcf0288b6de31080014ae92a30c8ba.png

2、新建一个 Controller 用来测试访问上面的IdentityServer

获取token,访问 http://localhost:5003/Idp/token ,提示访问成功

public class IdpController : Controller
{
private static readonly string _idpBaseUrl = "http://localhost:5002";
public async TaskToken(){
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(_idpBaseUrl);
if (disco.IsError)
{
return Content("获取发现文档失败。error:" + disco.Error);
}
var token = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest()
{
Address = disco.TokenEndpoint,
//ClientId、ClientSecret、Scope 这里要和 API 里定义的Client一模一样
ClientId = "client",
ClientSecret = "secret",
Scope = "api1"
});
if (token.IsError)
{
return Content("获取 AccessToken 失败。error:" + disco.Error);
}
return Content("获取 AccessToken 成功。Token:" + token.AccessToken);
}
}

37d087e3de9cbf83dd410070f0bec629.png

三、添加API资源

1、新建一个API项目

我把API项目和IdentityServer 放到同一个解决方案,这个自己定,无所谓的

API资源指的是IdentityServer IdpConfig.GetApis() 里面添加的 api1(这个api1名称随便起,但是要注意一定要保持一致)

添加认证之后就可以测试用 AccessToken 请求资源了

2、添加JWT 认证

StartUp.ConfigureServices()

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
// IdentityServer 地址
options.Authority = "http://localhost:5002";
//不需要https
options.RequireHttpsMetadata = false;
//这里要和 IdentityServer 定义的 api1 保持一致
options.Audience = "api1";
//token 默认容忍5分钟过期时间偏移,这里设置为0,
//这里就是为什么定义客户端设置了过期时间为5秒,过期后仍可以访问数据
options.TokenValidationParameters.ClockSkew = TimeSpan.Zero;
options.Events = new JwtBearerEvents
{
//AccessToken 验证失败
OnChallenge = op =>
{
//跳过所有默认操作
op.HandleResponse();
//下面是自定义返回消息
//op.Response.Headers.Add("token", "401");
op.Response.ContentType = "application/json";
op.Response.StatusCode = StatusCodes.Status401Unauthorized;
op.Response.WriteAsync(JsonConvert.SerializeObject(new
{
status = StatusCodes.Status401Unauthorized,
msg = "token无效"
}));
return Task.CompletedTask;
}
};
});

3、添加认证中间件

//这里注意 一定要在 UseMvc前面,顺序不可改变
app.UseAuthentication();

4、Controller 添加特性认证 [Authorize]

[Route("api/[controller]")]
[Authorize]
public class SuiBianController : Controller
{
[HttpGet]
public string Get(){
var roles = User.Claims.Where(l => l.Type == ClaimTypes.Role);
return "访问成功,当前用户角色 " + string.Join(',', roles.Select(l => l.Value));
}
}

5、测试

访问 http://localhost:5001/api/suibian ,提示 token 无效,证明我们增加认证成功

4fcc8aa474438cfa80c4fae3651e0cb1.png

四、客户端测试

1、修改 IdpController, 添加一个action 访问 API资源 /api/suibian

public class IdpController : Controller
{//内存缓存 需要提前注册 services.AddMemoryCache();private IMemoryCache _memoryCache; private static readonly string _idpBaseUrl = "http://localhost:5002";private static readonly string _apiBaseUrl = "http://localhost:5001";public IdpController(IMemoryCache memoryCache){
_memoryCache = memoryCache;
}public async TaskToken(){var client = new HttpClient();var disco = await client.GetDiscoveryDocumentAsync(_idpBaseUrl);if (disco.IsError)
{return Content("获取发现文档失败。error:" + disco.Error);
}var token = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest()
{
Address = disco.TokenEndpoint,
ClientId = "client",
ClientSecret = "secret",
Scope = "api1"
});if (token.IsError)
{return Content("获取 AccessToken 失败。error:" + disco.Error);
}//将token 临时存储到 缓存中
_memoryCache.Set("AccessToken", token.AccessToken);return Content("获取 AccessToken 成功。Token:" + token.AccessToken);
}public async TaskSuiBian(){string token, apiurl = GetApiUrl("suibian");
_memoryCache.TryGetValue("AccessToken", out token);if (string.IsNullOrEmpty(token))
{return Content("token is null");
}var client = new HttpClient();
client.SetBearerToken(token);var response = await client.GetAsync(apiurl);var result = await response.Content.ReadAsStringAsync();if (!response.IsSuccessStatusCode)
{
_memoryCache.Remove("AccessToken");return Content($"获取 {apiurl} 失败。StatusCode:{response.StatusCode} \r\n Token:{token} \r\n result:{result}");
}return Json(new
{
code = response.StatusCode,
data = result
});
}private string GetApiUrl(string address){return _apiBaseUrl + "/api/" + address;
}
}

2、请求 AccessToken

http://localhost:5003/Idp/token ,请求成功后会将 token 存储到 cache 中

37d087e3de9cbf83dd410070f0bec629.png

3、请求 API 资源

http://localhost:5003/Idp/suibian ,token是直接在缓存里面取出来的

3a0dc53d30d85a4082d28c359668af33.png

五、项目目录

c267af56f0c50096f8d4833554e87feb.png

- EOF -

推荐阅读  点击标题可跳转

.NET hbase client--终于浮出水面的轮子

WinUI 3 试玩报告:10 篇热文汇总

ASP.NET Core监听SQL Server数据库的实时信息

看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能 

a057b154700994dc6d9967808ed96563.png

好文章,我在看❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/350494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV访问像素点的灰度值

1.Mat矩阵数值的存储方式 这里以指针的方式访问图像素为例 (1)单通道 定义一个单通道图像&#xff1a; cv::Mat img_1 (320, 640, CV_8UC1, Scalar(0)); 对于单通道M(i,j)即为第i行j列的其灰度值&#xff1b;程序中表示为&#xff1a; img_1.ptr<uchar>(i)[j]; (2)多通道…

asp.net中大文件下载

因为IIS支持的最大文件为int32的最大值位数的文件下载&#xff0c;所以&#xff0c;超过2G的文件无法通过IIS进行下载。 通过网上查找的资料&#xff0c;如下可实现文件的下载&#xff0c;使用filestream进行下载。 public void download(){System.IO.Stream iStream null;byt…

Java的终结器仍然存在

当我第一次学习Java并从C 过渡到Java时&#xff0c;我记得我经常被告知&#xff0c;经常读到它不应该像C 析构函数那样对待Java终结器&#xff0c;也不应该依靠它。 该建议的频率和坚持性对我产生了影响&#xff0c;以至于我无法回忆起我上一次编写finalize&#xff08;&#x…

时隙aloha协议仿真程序_工控ModbusTCP/IP协议仿真环境搭建

01ModbusTCP/IP协议简介Modbus TCP/IP是简单的、中立厂商的用于管理和控制自动化设备的MODBUS系列通讯协议的派生产品。它覆盖了使用TCP/IP协议的“intranet”和“internet”环境中MODBUS报文的用途。协议的最通用用途是为诸如PLC’S&#xff0c;I/O模块&#xff0c;以及连接其…

vector的初始化及常用操作

1.vector的初始化&#xff1a;可以有五种方式,举例说明如下&#xff1a; &#xff08;1&#xff09; vector<int> a(10); //定义了10个整型元素的向量&#xff08;尖括号中为元素类型名&#xff0c;它可以是任何合法的数据类型&#xff09;&#xff0c;但没有给出初值&a…

查看Linux版本

suse版本 lsb_release -a suse版本之间差距还是有的&#xff0c;在suse12.2跑的脚本没有问题&#xff0c;到suse12.4上就出现问题了。 centos版本 cat /etc/redhat-release 转载于:https://www.cnblogs.com/jkhere/p/10900659.html

ps法线贴图插件_法线与置换贴图原理讲解以及烘焙制作!

​首先在讲解之前先给大家讲解下什么是法线贴图&#xff0c;法线贴图其实就是一张带有颜色的凹凸贴图&#xff0c;分别是有红绿蓝&#xff0c;三种颜色构造而成的&#xff0c;如下图所示&#xff1a;每一个颜色通道分别控制了每个像素的方向&#xff0c;当你把法线贴图用到低解…

从向量中读取元素:

从向量中读取元素&#xff1a; 1通过下标&#xff1a; int a[6] { 1,2,3,4,5,6 }; vector<int> b(a, a 4); for (int i 0; i < b.size() - 1; i) cout << b[i] << " "; 2通过迭代器 int a[6] { 1,2,3,4,5,6 }; vector<int> b(a, …

Nim博弈

忽然发现博弈论是个很好玩的东西哎 之前假期学长讲课的时候就发现这种必胜的战略可以用来坑人做题 这两天终于做了第一道博弈论的题&#xff0c;写篇博客纪念一下 灵感来源&#xff1a;洛谷P1247 Pre-scene 众所周知&#xff0c;李明和Jenny都喜欢Danny&#xff0c;为了争夺Dan…

java调用怎么调用方法区_Java中的方法调用有多昂贵

java调用怎么调用方法区我们都去过那儿。 在查看设计不良的代码的同时&#xff0c;听听作者对人们永远不应该牺牲性能而不是设计的解释。 而且&#xff0c;您不能说服作者摆脱其500行方法&#xff0c;因为链接方法调用会破坏性能。 好吧&#xff0c;这可能在1996年左右是正确的…

python中的np array函数_numpy中的np.ascontiguousarray()函数

"Return a contiguous array (ndim > 1) in memory (C order)."用途ascontiguousarray函数将一个内存不连续存储的数组转换为内存连续存储的数组&#xff0c;使得运行速度更快。C order vs Fortran orderC order 指的是行优先的顺序(Row-major Order)&#xff0c;…

OpenCV版本

#include <opencv2/opencv.hpp>using namespace cv;void main(){/*printf("\t当前使用的opencv版本为 OpenCV"CV_VERSION);getchar();*/std::cout << "\t当前使用的opencv版本为 OpenCV" << CV_VERSION << std::endl;system(&quo…

使用jstat的JVM统计信息

过去&#xff0c;我已经写过关于Oracle和/或OpenJDK Java开发工具包&#xff08;JDK&#xff09;随附的几个命令行工具的信息&#xff0c;但是我从来没有专门写过jstat工具 。 Oracle JDK 9文档Early Access指出jstat用于“监视Java虚拟机&#xff08;JVM&#xff09;统计信息”…

每天一点点之 taro 框架开发 - taro路由及传参

1.路由 taro的路由是自带的&#xff0c;不需要我们额外配置&#xff0c;只需要我们在app.js下config中配置pages即可 class App extends Component {config {pages: [pages/test/test,pages/index/index],} } 2.taro通过api实现跳转&#xff0c;替换 官网地址&#xff1a;taro…

调用支付jsapi缺少参数:total_fee_小程序支付问题怎么解决?

微信小程序开发的过程一定会遇到各种问题&#xff0c;最让人棘手的就是支付问题&#xff0c;因为没有支付做商城类似的小程序就没有办法完成最关键的一步。那么支付失败到底什么原因呢&#xff1f;一下子收集了几个错误类似&#xff0c;希望对你有帮助&#xff1a;No.1{err_cod…

Visual Stutio中win32控制台应用程序、win32项目、MFC项目的区别:

我的理解&#xff0c;我首先把这几个货分为两大类&#xff1b;第一类包括win32控制台应用程序&#xff0c;第二类就是剩下那俩货。而剩下那俩货又有一个包含关系&#xff0c;即win32项目包含mfc。&#xff08;我个人是这个区分的。&#xff09; 一、 区别: &#xff08;1&…

二分图匹配【模板】

传送门&#xff1a; #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define ll long long #define re register const int N1005; inline void read(int &a) {a0;int d1;char ch;while(chgetchar(),ch>9||ch<0)if(…

c++两个数组对比去掉重复的元素_30 数组案例

数组案例案例一&#xff1a;筛选指定数组元素要求&#xff1a;将数组[2,0,6,1,77,0,52,0,25,7]中的0去掉后&#xff0c;形成一个不包含0的新数组。var arr [2,0,6,1,77,0,52,0,25,7];var newArr [];for(var i0; i<arr.length; i){if(arr[i]!0){newArr[newArr.length]arr[i…

排序并记录排序前的索引(类似matlab sort函数)

这里用到vector比较方便。 #include<iostream> #include<vector> #include<algorithm> using namespace std; struct num_label { int num; int label; }; //自定义“大于” bool comp(const num_label &a, const num_label &b) { return a.n…

selenium实现登录百度(自动识别简单验证码)

需要做的工作 0、工程结构 1、代码&#xff1a; ①baidu_login.py 1 import re2 import os3 import sys4 import time5 import random6 from selenium import webdriver7 from PIL import Image, ImageEnhance8 import pytesseract9 from func import base642str, str2base6410…