API裸奔是绝对不容许滴,以前专门针对这块分享了jwt的解决方案(WebApi接口裸奔有风险);那若是是微服务,又怎么解决呢?每个服务都加认证受权也能够解决问题,只是显得认证受权这块冗余,重复在搞事情;IT大佬确定容忍不了,对于微服务架构,统一的认证受权中心那是必须的。前端
随着.NetCore的发布,IdentityServer4随之而出,是.Net Foundation的成员之一,专门针对.NetCore而出的认证受权框架,当前.Net圈是比较火的啦;再配上微服务认证受权的必要性,我决定以此开始入手进行微服务架构学习分享;c#
主要的学习分享思路为敲代码为向导,若是遇到相关理论概念,结合代码案例进行解释,不在单独针对理论知识整理相关文章(主要是担忧概括总结很差,让小伙伴疑惑,因此就想着结合应用案例解释比较容易理解)。后端
IdentityServer4 主要的功能就是认证和受权,其余功能这里先伪装不知道;主要目的就是想用其统一保护各个微服务的接口;先来理解一下认证和受权:api
受权(Authorization):在用户身份认证经过以后,授予用户访问资源的过程或是用户授予第三系统访问本身资源的过程,资源多是我的信息、文件、数据、接口等;OAuth2是如今比较火的受权标准,对于受权流程,后续会举例说明;浏览器
在公司,假如小伙伴是领导,在出差或休假的时候,一般会经过口头、邮件、信息等方式将一些工做临时委托给某人处理,好比签字、参会等,这个过程叫作受权,若是没有受权,签字无效,也不能随意参会;安全
认证(Authentication):用户身份认证,能够将其理解为登陆;系统验证身份凭据是否合法,好比用户名/密码、人脸识别等方式;OpenId Connect是目前比较流行的身份认证标准协议,OpenID是一个去中心化的网上身份认证系统,OpenID Connect是在OAuth2基础进行扩展,增长身份认证和相关身份标识信息;服务器
稍微有点规模的公司,一般都有本身的办公楼,有专门的保安人员,管控非公司人员的进入, 若是是公司人员,刷卡识别便可进入,若是是非公司人员须要登记我的信息确认才能进入,这个过程能够理解为身份认证;只有验证信息以后才能进入公司。架构
IdentityServer4 已经将OpenID Connect和OAuth 2.0封装实现,开发者开箱即用,无需再从新本身实现细节,但若是有须要,小伙伴能够在IdentitySever4基础进行扩展个性化需求;框架
在受权过程当中,根据应用场景不一样,有四种受权模式能够选择,以下:前后端分离
其余理论先不说了,咱们边撸码边聊,这样记忆深入一点,这里就从最简单的Client Credentials开始:
客户端模式没有用户,就只是单纯的机器对机器的交互,大概的流程以下:
流程简要说明:
来,结合流程看看代码怎么实现,一步一步来:
建立一个OrderController,并在里面新增一个Orders 接口,接口没有进行保护;
接口没有进行保护,能够任意访问,以下:
以上的API接口裸奔是有风险的,如今须要统一的认证受权中心进行保护,以下:
新建立一个API项目,并引入IdentityServer4包,并在内存中模拟相关数据,方便测试;
术语解释:
ApiScope:就是一个做用域范围,生成的Token只能访问指定范围的资源;
Client:这里的客户端就是应用,好比MVC项目、纯前端项目、Winfrom/WPF、APP等,必须首先在受权服务器中进行备案并得到受权服务器分配的标识和密码,后续用于获取AccessToken;
模拟数据准备好了,就在Startup中进行对应的注入和配置,并开启中间件,以下:
这样就初步完成受权服务器的搭建,这里监听的端口改成6100了,用Postman先来测测是否能正常获取Token,以下:
可能有新手小伙伴会问,咋知道是这个地址能获取token的? 小伙伴能够在浏览器中输入如下连接,便可看见受权服务器的相关信息(受权服务器地址+/.well-known/openid-configuration):
受权服务器已经好了,准备将资源服务器接入到受权服务器,对API接口进行保护(ApiDemo项目中),以下:
注:ApiDemo项目中须要Microsoft.AspNetCore.Authentication.JwtBearer包,由于项目是基于.NetCore3.1的,因此这里引用的包版本为3.1.10。
而后在接口上面加上[Authorize]特性,将接口保护起来,看运行效果以下:
在Postman中测试,先获取AccessToken,而后将获取的AccessToken加入到Header中请求资源服务器中受保护的API,以下:
建一个控制台项目,具体步骤如图:
这里就不用文字说明步骤,小伙伴一边看代码,一边看注释,这样应该比较清晰点:
static async Task Main(string[] args) { // 1. 建立一个HttpClient用于请求 var client = new HttpClient(); // 2. 获取受权服务器的相关信息,IdentityModel已经将其封装好了 var disco = await client.GetDiscoveryDocumentAsync("http://localhost:6100"); // 3. 检查是否请求错误 if (disco.IsError) { // 错误就打印错误信息,而后直接返回 Console.WriteLine(disco.Error); return; } // 4. 经过受权服务分配的标识,向受权服务器请求AccessToken var tokenResp = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest { // 指定获取token的地址,IdentityModel进行封装,直接使用便可 Address = disco.TokenEndpoint, // 指定受权服务器分配的客户端标识 ClientId = "client", // 指定受权服务器分的客户端密码 ClientSecret = "ordersecret" }); // 5. 检查获取Token是否成功 if (tokenResp.IsError) { // 若是失败,打印错误消息并返回 Console.WriteLine(tokenResp.Error); return; } // 6. 建立一个请求API资源的HttpClient var apiClient = new HttpClient(); // 7. 将获取到的Token以Bearer的方案设置在请求头中 apiClient.SetBearerToken(tokenResp.AccessToken); // 8. 向资源服务器中请求受保护的API var contentResp = await apiClient.GetAsync("http://localhost:5000/api/Order"); // 9. 打印对应的消息 if (contentResp.IsSuccessStatusCode) { var content = await contentResp.Content.ReadAsStringAsync(); Console.WriteLine(JArray.Parse(content)); } else { Console.WriteLine(contentResp.StatusCode); } Console.ReadLine(); }
到这里离完成还差一步了,什么,资源不是保护了吗,受保护资源也能正常访问了,还差哪一步?
在受权服务器模拟备案客户端的时候,是否是指定了访问资源的做用域,也就是说,备案过的客户端只能访问被受权的API资源,而如今拿到的AccessToken都能访问资源服务器中全部受保护的资源,那是由于资源服务器中的API资源没有限制做用域访问,而在实际项目中,并非拿到AccessToken就能随便访问,须要作限制,继续往下看↓↓↓
假如指定的scope值和客户端在受权服务器中备案时设置的不同,就算获取到AccessToken也不能正常访问资源,会报403错误,这里我不截图,小伙伴下去试试。
可能小伙伴会比较急,这都是啥玩意,全是硬编码,垃圾文; 别别别,说好的学习分享嘛,一步一个脚印来嘛,最终确定是小伙伴想要的,也是我学习的目标;
关于客户端凭据生成的Token,在jwt.io网站解析看看,记录一下,看看后面有用户参与的状况,生成的Token解析出来会有什么不一样呢,先上个图(图中解析出来的属性以前在WebApi接口裸奔有风险有说过):
从这篇开始,后续会尽快更新学习分享,小伙伴们加入一块儿学习,一块儿讨论。下一篇说说Resource Owner Password Credentials.
一个被程序搞丑的帅小伙,关注"Code综艺圈",跟我一块儿学~