基于IdentityServer4 实现.NET Core的认证授权
IdentityServer4是什么?
IdentityServer4是基于ASP.NET Core实现的认证和授权框架,是对OpenID Connect和OAuth 2.0协议的实现。
OpenID Connect 和 OAuth2.0是什么
OpenID Connect:
OpenID Connect由OpenID基金会于2014年发布的一个开放标准, 是建立在OAuth 2.0协议上的一个简单的身份标识层, OpenID Connect 兼容 OAuth 2.0. 实现身份认证(Authentication)
参考资料:https://openid.net/connect/
OpenID Connect文档:https://openid.net/specs/openid-connect-discovery-1_0.html
OAuth2.0:
OAuth2.0是一个开放的工业标准的授权协议(Authorization),它允许用户授权让第三方应用直接访问用户在某一个服务中的特定资源,但不提供给第三方账号及密码信息
参考资料:https://www.cnblogs.com/xiandnc/p/9763121.html
OAuth2.0 文档:https://tools.ietf.org/html/rfc6749#page-73
Authentication 和 Authorization的区别
authentication: n. 证明;鉴定;证实
authorization: n. 授权,认可;批准,委任
前者是身份识别,鉴别你是谁;后者是授权许可,告诉你可以做什么。
举个例子:你吭哧吭哧写了一天的代码,急于回家吃上一口媳妇做的热饭。当你走到小区门口的时候你需要刷小区的门禁卡才能进入到小区里面,然后再找到你家在哪一栋楼,几单元几号,然后掏出钥匙开门才能回到家。在这个过程中刷小区的门禁就是认证你是这个小区的人,拿你家的钥匙开门就是授权的过程,如果你的认证不通过,那就不存在授权。
OAuth2.0的原理
我们先来了解一下OAuth2.0中的几个关键概念:
资源所有者(Resource Owner):
一个能够访问受保护资源的实体。当资源所有者是一个人时,它被称为终端用户
资源服务器(Resource Server):
托管受保护资源的服务器,能够使用访问令牌接受和响应受保护的资源请求
客户端(Client):
代表资源所有者和其授权的应用程序来保护资源请求。术语客户端并不意味着任何特定的实现特征(例如,应用程序是否在服务器、桌面或其他设备上执行)
授权服务器(Authorization Server):
在成功验证资源所有者并获得授权之后,服务器向客户端发出访问令牌。(授权服务器是用来管理Resource Owner,Resource Server,Client的中间人)
场景:小李想要打印(美图快印)自己三年来发布在新浪微博相册中和女朋友的照片,有没有什么方法他既不告诉工作人员自己的新浪微博用账号和密码又能够方便快捷的把照片给到美图快印呢?(排除存U盘这种手工操作)

Authorization Server和Resource Server可以使独立的服务提供商,也可以是在一起的,比如例子中新浪微博既作授权服务器也用来存储用户的图片资源。我们可以看到OAuth2解决的问题是:通过Authorization Server可以提供一个访问的凭据(token)给client(美图快印的工作人员),使得client可以在不知道Resource Owner以及Resource Server的用户名和密码的情况下访问到Resource Owner受保护的资源,它是一个完美的中间人。
OAuth2.0详细内容请参考:https://www.cnblogs.com/xiandnc/p/9763121.html
IdentityServer4能做什么

用户认证服务
基于OpenID Connect实现的独立的认证服务实现对多平台(web, native, mobile, services)的集中认证
API访问授权
为各种类型的客户机颁发api访问令牌,例如服务器到服务器、web应用程序、spa和native/mobile程序
联合身份认证
支持外部身份提供者,如Azure Active Directory、Google、Facebook等
定制化的实现
IdentityServer4的许多方面可以定制以满足您的需要,因为它是一个框架,而不是SaaS服务,所以可以通过编写代码来调整实现,以适应不同的场景
成熟的开原方案
使用许可的Apache2开源协议,允许在其之上构建商业产品,也作为.NET基金会支持的项目 (https://dotnetfoundation.org/projects?type=project&ps=10&pn=6)
提供免费的商业支持
官方可以对使用者提供部分的免费商业支持
IdentityServer4定义的基本术语

IdentityServer
身份认证服务器是一个实现了OpenID Connect和OAuth 2.0协议的身份提供者,它负责向客户端发布安全令牌
User
使用注册客户端访问资源的用户
Client
客户端从标识服务器请求令牌,要么用于认证用户(请求身份令牌),要么用于访问资源(请求访问令牌)
客户端必须首先在身份服务器上注册,然后才能请求令牌
这里的客户端可以是web应用程序、native mobile, desktop applications, SPA 等程序
Resource
资源是你想要用身份认证服务器保护的东西,如:用户的身份数据或api
每个资源都有一个惟一的名称,客户端使用这个名称来指定他们想要访问的资源
关于用户的身份数据标识(也称为claim),例如姓名或电子邮件地址
Identity Token
身份令牌代表身份验证过程的结果
Access Token
访问令牌授权客户端以允许访问哪些API资源,访问令牌包含客户端和用户的信息
IdentityServer4的简单示例
我们先来看一个简单的例子,我们有三个API ,Order, Product, Inventory,我们利用IdentityServer4来实现对着三个API的认证和授权。首先我们需要一个实现认证和授权的服务,然后外部要想访问我们的API就必须通过统一的认证和授权服务的任何才可以,否则就是返回401: UnAuthorized ,未经授权的访问。我们既可以将身份信息存储到内存中,也可以将其持久化到数据库中,此处我们使用内存模式快速的演示实现(示例代码中也支持存储到DB中,使用SqlLite + EF Core)
首先我们需要安装IdentityServer4的Nuget包,然后在ConfigureServices方法中添加如下代码来初始化需要保护的API资源信息,代码如下:
public void ConfigureServices(IServiceCollection services)
{
// config data in memory
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(InitMemoryData.GetApiResources())
.AddInMemoryClients(InitMemoryData.GetClients())
.AddTestUsers(InitMemoryData.GetUsers()); // config in DB
//services.AddDbContext<IdentityServerDbContext>(options =>
// options.UseSqlite(sqliteConnection));
}
InitMemoryData 中的配置信息如下:
// scopes define the API resources in your system
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("inventoryapi", "this is inventory api"),
new ApiResource("orderapi", "this is order api"),
new ApiResource("productapi", "this is product api")
};
} // clients want to access resources (aka scopes)
public static IEnumerable<Client> GetClients()
{
// client credentials client
return new List<Client>
{
new Client
{
ClientId = "inventory",
AllowedGrantTypes = GrantTypes.ClientCredentials, ClientSecrets =
{
new Secret("inventorysecret".Sha256())
}, AllowedScopes = { "inventoryapi" }
},
new Client
{
ClientId = "order",
AllowedGrantTypes = GrantTypes.ClientCredentials, ClientSecrets =
{
new Secret("ordersecret".Sha256())
}, AllowedScopes = { "orderapi" }
},
new Client
{
ClientId = "product",
AllowedGrantTypes = GrantTypes.ClientCredentials, ClientSecrets =
{
new Secret("productsecret".Sha256())
}, AllowedScopes = { "productapi" }
}
};
}
我们给IdentityServer4设置启动端口5000,认证服务的地址就是:http://localhost:5000
然后认证Server端的代码就好了,接下来我们需要在API添加授权服务的配置,配置都很类似,我们以OrderAPI为例:
// 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(); services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "orderapi";
});
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvc();
}
这里我们配置的Authority地址就是认证授权的地址,AddAuthentication中的Bearer是Jwt Token的一种,具体可参考文章:https://www.cnblogs.com/Leo_wl/p/7792046.html
在controller中添加简单代码来返回API的信息:
[Route("[controller]")]
[Authorize]
public class OrderController : ControllerBase
{
// GET api/order
[HttpGet]
public IActionResult Get()
{
var userIdentitys = from c in User.Claims
select new UserIdentity
{
Type = c.Type,
Value = c.Value
};
var result = new UserIdentityModel()
{
Description = "Access user order api successfully",
UserIdentitys = userIdentitys.ToList()
};
return new JsonResult(result);
}
}
设置当前API的端口为:5002
Product和Inventory中的配置和这个类似,端口信息以此设置为5001,5003,一切就绪,让我们来测试一下结果:
启动IdentotyServer,以及三个API,我们使用Postman来请求api,下面站点就是IdentityServer的页面了:

接着我们来直接访问OrderAPI就会发现返回 401 ,这说明目前我们的API已经受保护了,没有认证服务颁发的token,是直接访问不了的。

我们输入地址:http://localhost:5000/.well-known/openid-configuration 可以查看我们当前认证授权服务的配置信息:

现在还差一步就可以访问我们的OrderAPI了,那就是:客户端传入必要的信息给认证服务,生成一定格式的token,然后携带着这个token来访问我们的服务

传入的三个参数分别是grant_type , client_sercret, client_id这几个参数分别代表了我们申请token时的授权方式是客户端授权,密匙,clientid信息。我们在前面介绍过IdentityServer4是对OAuth2.0的实现,所以具体参数的含义请参考之前OAuth2.0文章中的详细介绍
https://www.cnblogs.com/xiandnc/p/9763121.html
此时我们可以看到认证服务给我们返回了有效token,指定过期时间3600s ,token的类型是Bearer,然后我们再携带这这个token去访问服务试试看:

我们可以看到此时API 返回了我们期待的正确结果,如果在1小时后再携带着这个token去访问API就会提示token已过期,需要重新生成才能够继续访问。看完这个例子是不是很简单,很清爽呢
例子参考代码:https://github.com/KenWang007/IdentityServer4Demo
基于IdentityServer4 实现.NET Core的认证授权的更多相关文章
- 一款基于.NET Core的认证授权解决方案-葫芦藤1.0开源啦
背景 18年公司准备在技术上进行转型,而公司技术团队是互相独立的,新技术的推动阻力很大.我们需要找到一个切入点.公司的项目很多,而各个系统之间又不互通,导致每套系统都有一套登录体系,给员工和客户都带来 ...
- ASP.NET Core JWT认证授权介绍
using JWTWebApi.Models; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetC ...
- 一看就懂的IdentityServer4认证授权设计方案
查阅了大多数相关资料,总结设计一个IdentityServer4认证授权方案,我们先看理论,后设计方案. 1.快速理解认证授权 我们先看一下网站发起QQ认证授权,授权通过后获取用户头像,昵称的流程. ...
- 基于.NetCore3.1系列 ——认证授权方案之Swagger加锁
一.前言 在之前的使用Swagger做Api文档中,我们已经使用Swagger进行开发接口文档,以及更加方便的使用.这一转换,让更多的接口可以以通俗易懂的方式展现给开发人员.而在后续的内容中,为了对a ...
- 【ASP.NET Core学习】使用JWT认证授权
概述 认证授权是很多系统的基本功能 , 在以前PC的时代 , 通常是基于cookies-session这样的方式实现认证授权 , 在那个时候通常系统的用户量都不会很大, 所以这种方式也一直很好运行, ...
- .net core gRPC与IdentityServer4集成认证授权
前言 随着.net core3.0的正式发布,gRPC服务被集成到了VS2019.本文主要演示如何对gRPC的服务进行认证授权. 分析 目前.net core使用最广的认证授权组件是基于OAuth2. ...
- asp.net core 使用identityServer4的密码模式来进行身份认证(2) 认证授权原理
前言:本文将会结合asp.net core 认证源码来分析起认证的原理与流程.asp.net core版本2.2 对于大部分使用asp.net core开发的人来说. 下面这几行代码应该很熟悉了. s ...
- .Net Core权限认证基于Cookie的认证&授权.Scheme、Policy扩展
在身份认证中,如果某个Action需要权限才能访问,最开始的想法就是,哪个Action需要权限才能访问,我们写个特性标注到上面即可,[TypeFilter(typeof(CustomAuthorize ...
- .Net Core 认证系统之基于Identity Server4 Token的JwtToken认证源码解析
介绍JwtToken认证之前,必须要掌握.Net Core认证系统的核心原理,如果你还不了解,请参考.Net Core 认证组件源码解析,且必须对jwt有基本的了解,如果不知道,请百度.最重要的是你还 ...
随机推荐
- 自己制作一个USB自动挖矿器
先讲下设备效果: 对面坐着一位同事中午去吃饭没锁屏幕,这时候你想用他的电脑去挖矿, 挖矿,当然不可能跑到他的座位上,关掉360然后下载个挖矿软件什么的.... 这时候你只需要花十块钱制作如下设备,然后 ...
- [zt]C++二维数组讲解、二维数组的声明和初始化
定义: int *pia = new int[10]; // array of 10 uninitialized ints 此 new 表达式分配了一个含有 10 个 int 型元素的数组,并返回指向 ...
- angular.isUndefined()
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 动态规划-LIS1
https://vjudge.net/contest/297216?tdsourcetag=s_pctim_aiomsg#problem/J #include<bits/stdc++.h> ...
- G102040I
傻逼题.我从来没见过eps这样的... 打破了我对计算几何美好的幻想. eps=1e-6=>wa3 eps=1e-8->wa2 eps 1e-4->AC 真的自闭,真的猜不到ep ...
- layui 表格在排序之后没有重新渲染问题
问题描述: 在layui表格中,最后一列增加了操作按钮,并且在某些行设置了样式,但是在排序之后,按钮的点击事件失效了,样式也没有了,可能是没有执行done回调 原因: done回调只有在render和 ...
- error: can't copy 'docx\templates\default-docx-template': doesn't exist or not a regular file --------------- Failed building wheel for python-docx; python-docx的安装使用;python操作word
本人第一安装python-docx很不幸就出现了,如下的错误:(如果你也遇到同样的错误,不要慌可以参考下面解决方案,由于第一次处理这种错误,如有不对欢迎大家多多批评指正) 问题所在是因为我们的setu ...
- CASE WHEN 高阶用法?
两个表做关联时,以左表为准,若左表某列不为空,则与右表对应列进行关联匹配,为空则不做匹配. 以上做法,有一种说不出来的感觉,不管怎样,问题是解决了. 如有更好的解决思路,请留言告知,不甚感激!
- Dubbo架构设计及原理详解
Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务模型的角度来看,Dubbo采用的是一种非常简单的模 ...
- 文末福利丨i春秋互联网安全校园行第1站精彩回顾
活动背景 为响应国家完善网络安全人才培养体系.推动网络安全教育的号召,i春秋特此发起“互联网安全校园行”系列活动.旨在通过活动和知识普及提升大学生信息安全意识,并通过线下交流.技能分享.安全小活动以及 ...