您现在的位置是:网站首页> 编程资料编程资料
详解IdentityServer4介绍和使用_实用技巧_
2023-05-24
358人已围观
简介 详解IdentityServer4介绍和使用_实用技巧_
一、概述
前几篇文章介绍到,OWIN提供了一些OAuth2.0认证的机制,使用OWIN可以很方便的实现OAuth2.0认证和授权。但是在.NETCORE中更倾向于使用Identityserver4组件来构建认证授权服务,原因是IdentityServer4 是为ASP.NET Core系列量身打造的一款基于 OpenID Connect 和 OAuth 2.0 认证框架。 具体的可以看下IDS4的官方文档。本文重点介绍IDS4实际使用过程中涉及到的技术点。下面先简单介绍下IDS4中涉及到的概念及简单使用流程。
OpenID是Authentication,即认证,对用户的身份进行认证。
OAuth是一个开放标准,是Authorization,即授权,允许用户授权第三方移动应用访问他们存储在其他服务商上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。OAuth允许用户提供一个令牌而不是用户名和密码来访问他们存放在特定服务商上的数据。每一个令牌授权一个特定的网站内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth可以允许用户授权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非所有内容。
OIDC是OpenID Connect的简称,是一个基于OAuth2协议的身份认证标准协议。是认证和授权的结合。OAuth2是一个授权协议,它无法提供完善的身份认证功能,OIDC使用OAuth2的授权服务器来为第三方客户端提供用户的身份认证,并把对应的身份认证信息传递给客户端,且可以适用于各种类型的客户端(比如服务端应用,移动APP,JS应用),且完全兼容OAuth2,也就是说你搭建了一个OIDC的服务后,也可以当作一个OAuth2的服务来用。

1、OpenID认证用户的流程

- 用户访问xxx.com(该网站支持OpenID)
- xxx.com将用户导向OpenID服务的登录页面
- 用户输入用户名密码,成功后回调到xxx.com网站,并携带用户在OpenID服务中的唯一标识(这个表示可能仅仅是一个GUID,不含用户个人信息)
- xxx.com校检成功后,就认为用户完成了登录认证
OpenID 目的就是做认证,使用简单,不透露用户的个人信息。
2、OAuth认证用户的流程
OAuth是用来做授权的,如果用来做认证,具体的流程如下图所示:

- 用户使用QQ登录HelloFont
- HelloFont将用户导向QQ授权服务的登录页面
- 用户登录成功并授权后,页面返回HelloFont并携带访问令牌
- 如果想获取用户的详细信息,还需要通过访问令牌再次调用QQ服务提供的相关接口进行请求
可以看出,OAuth 相对于 OpenID 最大的区别就是,网站实际上是拿到了用户帐户访问权限继而确认你的身份。同时OAuth还比OpenID多了几个操作步骤。
3、IdentityServer4对象
下面简单的介绍下Identityserver4中涉及的对象,具体的可以参考下官方文档。
- 用户(User):用户是使用已注册的客户端(指在id4中已经注册)访问资源的人。
- 客户端(Client):客户端就是从identityserver请求令牌的软件(你可以理解为一个app即可),既可以通过身份认证令牌来验证识别用户身份,又可以通过授权令牌来访问服务端的资源。但是客户端首先必须在申请令牌前已经在identityserver服务中注册过。
- 资源(Resources):资源就是你想用identityserver保护的东东,可以是用户的身份数据或者api资源。
- 身份令牌(顾名思义用于做身份认证,例如sso其实主要就是用于身份认证):一个身份令牌指的就是对认证过程的描述。它至少要标识某个用户(Called the sub aka subject claim)的主身份信息,和该用户的认证时间和认证方式。但是身份令牌可以包含额外的身份数据,具体开发者可以自行设定,但是一般情况为了确保数据传输的效率,开发者一般不做过多额外的设置,大家也可以根据使用场景自行决定。
- 访问令牌(用于做客户端访问授权):访问令牌允许客户端访问某个 API 资源。客户端请求到访问令牌,然后使用这个令牌来访问 API资源。访问令牌包含了客户端和用户(如果有的话,这取决于业务是否需要,但通常不必要)的相关信息,API通过这些令牌信息来授予客户端的数据访问权限。
二、IdentityServer4实践
1、构建非持久化认证服务项目
下面简单的介绍下大体流程,看懂思路即可:
IDS4本身已经将OAuth2.0+OIDC+SSO思想给实现了,并且提供了成熟的组件IdentityServer4,如下图,只需要将该组件引入,进行相关的配置即可。

正常来说我们通过nuget下载了IdentityServer4包,就需要在startup.cs中引入使用,如下:
using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; namespace IdentityServer { public class Startup { public IHostingEnvironment Environment { get; } public Startup(IHostingEnvironment environment) { Environment = environment; } public void ConfigureServices(IServiceCollection services) { var builder = services.AddIdentityServer() .AddInMemoryIdentityResources(Config.GetIdentityResources()) .AddInMemoryApiResources(Config.GetApis()) .AddInMemoryClients(Config.GetClients()); if (Environment.IsDevelopment()) { builder.AddDeveloperSigningCredential(); } else { throw new Exception("need to configure key material"); } } public void Configure(IApplicationBuilder app) { if (Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseIdentityServer(); } } }可以从上面代码看出,采用的是本地配置文件的方式,我们看下配置文件:
using IdentityServer4.Models; using System.Collections.Generic; namespace IdentityServer { public static class Config { public static IEnumerable GetIdentityResources() { return new IdentityResource[] { new IdentityResources.OpenId() }; } public static IEnumerable GetApis() { return new List { new ApiResource("api1", "My API") }; } public static IEnumerable GetClients() { return new List { new Client { ClientId = "client", // no interactive user, use the clientid/secret for authentication AllowedGrantTypes = GrantTypes.ClientCredentials, // secret for authentication ClientSecrets = { new Secret("secret".Sha256()) }, // scopes that client has access to AllowedScopes = { "api1" } } }; } } } 在配置文件中我们定义了身份资源IdentityResource、API资源Apis、客户端Clients等等吧,具体怎么配置建议还是看一下官方文档,很详细,里面包含了相应的属性及示例等,可根据实际需求进行选择配置。
简单的认证服务就搭建好了,当然这个是比较简单的,支持客户端模式,不需要用户参与的授权。如果说站外应用需要使用授权码模式、或者implact模式,我们搭建的identityserver4项目还要提供登录授权等相关的页面的,不然用户在哪里登录和授权呢。这个官网也有示例,可以在github中搜索下载源码查看,直接使用他们提供的界面(mvc)即可,当然也可以自己进行UI优化,但是他们提供的action的名称最好不要更改,因为identityserver4包中退出、登录相关的跳转都是指定好的,通过示例来说明下为啥不建议改动:

截图中是identityserver4提供的界面代码(mvc),有个Account控制器,里面有退出登录、授权受限等action,如果站外应用使用授权码模式登录,发现授权受限或者用户退出登录,那么identityserver4服务会将用户指向Account/Logout或者Account/AccessDenied,如果把名称改了就找不到相应的action了。当然并不是所有的都不能改,比方说登录,我就自己单独在另一个action写的(有需求的原因),所以需要在startup.cs引入identityserver4的时候指定,如下:
//用户交互的选项 options.UserInteraction = new IdentityServer4.Configuration.UserInteractionOptions { LoginUrl = "/login/index",//登录地址 };还有一种办法就是将identityserver4源码进行二次开发,改成你想要的样子。。。
2、构建持久化认证服务项目
上边的identityserver4的配置信息是写死在文件中的,在实际开发中,还是要将配置信息写入到数据库中,所以就需要持久化了。另外还需要提供人为配置信息的管理界面。总的来说就是基于IdentityServer4包加两块功能:管理界面+持久化。如下图:

先来说持久化吧,我们先选择EFCore作为ORM,所以startup.cs引入identityserver4的方式稍微有点不同,因为要将数据保存到数据库中,另外还要引入efcore,来看下startup.cs:

具体代码如下(伪代码,主要是思路):
using HyIdentityServer4.Authorization; using HyIdentityServer4.Data; using HyIdentityServer4.Extention; using HyIdentityServer4.Implementation; using IdentityServer4.Services; using IdentityServer4.Validation; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System; using System.IO; using System.Reflection; using System.Security.Cryptography.X509Certificates; namespace HyIdentityServer4 { public class Startup { public Startup(IConfiguration configuration, IWebHostEnvironment environment) { Configuration = configuration; Environment = environment; } public IConfiguration Configuration { get; } public IWebHostEnvironment Environment { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //session配置 services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); }); //cookie samesite策略 services.AddSameSiteCookiePolicy(); #region 注入EFCore服务(支持mysql和sqlserver) #if DEBUG string connectionString = Configuration.GetConnectionString("HyIds4ConnectionDebug"); #else string connectionString = Configuration.GetConnectionString("HyIds4ConnectionRelease"); #endif bool isMysql = Configuration.GetConnectionString("IsMysql").ObjToBool(); if (isMysql) { services.AddDbContext(options => options.UseMySql(connectionString, MySqlServerVersion.LatestSupportedServerVersion)); } else { services.AddDbContext(options => options.UseSqlServer(connectionString)); }; #endregion #region 注入IdentityServer4服务 var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; var builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true;//是否引发错误事件 options.Events.RaiseInformationEvents = true;//是否引发信息事件 options.Events.RaiseFailureEvents = true;//是否引发失败事件 options.Events.RaiseSuccessEvents = true;//是否引发成功事件 //用户交互的选项 options.UserInteraction = new IdentityServer4.Configuration.UserInteractionOptions { LoginUrl = "/login/index",//登录地址 }; }) //IdentityServer4使用asp.net identity身份实现 .AddAspNetIdentity() //IdentityServer4采用EFCore的方式实现数据库模式 .AddConfigurationStore(options => { if (isMysql) { options.ConfigureDbContext = b => b.UseMySql(connectionString, MySqlServerVersion.LatestSupportedServerVersion, s
相关内容
- .net6 使用Senparc开发小程序配置过程_实用技巧_
- ASP.NET中Response.BufferOutput属性的使用技巧_实用技巧_
- .NET使用System.Timers.Timer类实现程序定时执行_实用技巧_
- 详解.NET主流的几款重量级 ORM框架_实用技巧_
- ASP.NET轻量级MVC框架Nancy的基本用法_实用技巧_
- ASP.NET Core通用主机实现托管服务_实用技巧_
- ASP.NET Core通用主机的系统配置_实用技巧_
- .Net ORM 访问 Firebird 数据库的方法_实用技巧_
- ASP.NET Core中的对象池介绍_实用技巧_
- ASP.NET Core的日志系统介绍_实用技巧_
点击排行
本栏推荐
