(恰似一江春水向东流)
最近听说IdentityServer4从v3升级到v4了,其实很简单,就是nuget包升级一下的事儿,不过没想到涉及到的内容还挺多,要不然也不会直接从3.1直接蹦到4.0,这么大的跨度,证明已经涉及到核心的类做了修改。
不要抱怨一直修改,毕竟已经很多人写了更新文档了,软件系统就是一直更新的过程。当然,如果不更新使用v3也可以,功能几乎都是一样的,但是我更喜欢更新到最新版本。相关代码已经放到了项目的4x分支(如果没有,说明已经上线,并迁到主分支了):
已经通过docker部署好了,现在大家看到的online效果,就是4x版本的。那下边就快速说说更新过程吧,放心,前方安全,并没有涉及到什么看不懂的原理。
最终更新的文件这么多:
01
PART
升级依赖包
升级肯定要从nuget包开始,以下这几个就是我认证中心项目使用的nuget包,一键升级全部,可以看到都是最新的了:
(升级nuget包)
操作确实是很简单,操作也在预料之中,只不过没想到会这么多(其实更多,因为这里仅仅是编译下的Errors,有些页面内的还没有被编译到):
那下边就开始动手迁移吧,再问一下自己,是否准备好了,3x版其实也可以。
02
PART
寻找模板
以下的是我的摸索历程,毕竟我看的代码和文章基本都是3x的。
01
更新官方模板
上边我们仅仅是更新了Ids4的核心库,我想象着官方既然更新了核心库,那他们的模板库已经也已经更新了,然后就卸载了这几个模板,又重新安装了一次:
相关的安装命令是这样的:
// 安装模板
dotnet new -i IdentityServer4.Templates
// 初始化项目
dotnet new is4admin --name Idp
因为我用的是快速启动项目,所以就直接生成了一个is4admin的项目,发现,事情并没有我想象的那么简单,他们基本还是3x版本的。
其实有一个是4x版本的,就是is4inmem版本的:
dotnet new is4inmem --name Idp
他这个是4x版本的,只不过是内存模式的,有很多地方还是和我们的不一样,没办法,只能寻找官网了。
02
查看源码
其实官方的源码很多也都还是3x版本的,毕竟模板都是这样,直接用文件查找的方式,一一的点开来看,最终还是找到了:
https://github.com/IdentityServer/IdentityServer4/tree/main/src/AspNetIdentity/host/Quickstart
当然官网有很多地方,最终我是在host文件夹下,才发现了4x版本的快速启动代码,然后开始针对错误一一的处理,主要的修改的地方有以下几个部分。
03
PART
主要修复部分
01
DB上下文部分
其实大家根据上边的报错一一修改就行了,我这里简单的列举下,心里有个谱。
本次升级到4x,数据库发生了变化,除了增加表以外,比如增加了IdentityResourceClaims表,然后也针对几个表,增删修改了几列字段,具体的我在下文会列举出来,自己更新的时候也可以看到,
所以我们就需要重新生成迁移报告和update数据库了,大家做好生产数据的备份和保护。
如果你不更新数据库迁移的话,肯定会遇到这个错误的:
除了修改了数据库表结构,也同时配套了几个数据库脚本,方便我们使用,具体的查看官方源码即可,基本的更新内容这些:
迁移到ConfigurationDbContext的新模式需要做以下更改:
添加列:Clients、ApiResources、apiscope和ApiScopeClaims
移除列:ApiScopeClaims和ApiScope
重命名表:ApiClaims、ApiProperties、ApiSecrets、IdentityClaims和IdentityProperties
添加表:添加两个新表——ApiResourceScopes和ApiResourceProperties
有关新的范围和资源建模的更多细节,请参考IdentityServer4文档。
迁移到PersistedGrantDbContext的新模式需要做以下更改:
新列:为DeviceCodes和PersistedGrants添加列
为了使转换更容易,我们创建了几个脚本,涵盖四种不同的数据库类型:
MySQL
MsSQL
PostgreSQL
SQLite
可以看到这次升级,只是Ids4相关的组件库,并没有涉及到微软的Identity类库七个用户相关的表,所以用户数据不会丢失。也不用迁移用户数据。
PS:迁移的时候,如果是用我的项目,手动执行下那四个命令,不过相信每个玩过efcore的都明白如何操作:
1、PM> add-migration InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
2、PM> update-database -c PersistedGrantDbContext
3、PM> add-migration InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
4、PM> update-database -c ConfigurationDbContext// 因为不用迁移用户数据,所以不用管用户上下文
整个过程没有报错,虽然它提示说可能造成数据丢失,但是并没有
很流畅的就下来了,只是最后有一个小插曲,就是迁移好后,然后重新生成了容器镜像等,前端admin项目访问的时候,提示没有scope,后来发现Enabled为false了,不知什么时候被改了,修改为true就行了。
除了这个小插曲,文末的问题才是最重要的,但是也是很简单的,不要慌,往下看就是了。
02
控制器API方面
既然我们的数据库表结构都变了,那控制器的一些API和视频模型肯定也会有变化的,这是肯定的,具体我就不好列举了,涵盖以下几个部分:
AccountController、ConsentController、DeviceController、GrantsController、这四部分。
其实不要感觉更新的内容很多,都是很简单的几处,自己稍微看一看,或者用上边官方源代码覆盖下就好了。
03
视图部分
理所应当的,视图模型变了,那我们的页面也需要调整:
就是这么多,对应修改下就行了。
整个过程大概持续了30~60分钟,全程并没有很难受的地方,都是粘贴复制啥的。只要心静就可快速搞定。
更新完成以后,可以看到项目已经没有问题了,但是这个时候还会剩下一个小知识点,看startup.cs就知道了。
04
PART
配置源地址
如果你之前用过Ids4,肯定都知道那个梗,就是本地开发的时候一切正常,如果配置到服务器,源地址一直是localhost域名,之前我也写过一篇文章来讲如何处理这个问题,主要就是用到的是上边截图中,配置PublicOrigin这个属性即可,但是这次在4x版本中,这个api被删掉了。
如果你不做配置的话,会看到这个情况:
找了很多资料,最后还是在官方开源项目的Issue中发现了,看来还是得多看Issue,可能官方也发现3x升级4x有很多问题,干脆直接Pinned了一个issue:
最终的解决方案其实有两种,第一种很简单,直接在中间件的最外层,也就是最上边,添加配置:
app.Use(async (ctx, next) =>{ctx.SetIdentityServerOrigin("https://xxx.com");await next();});
其实就是SetIdentityServerOrigin方法。
第二种就稍微复杂了些,需要三步:
配置服务:
services.Configure<ForwardedHeadersOptions>(options =>
{options.ForwardedHeaders =ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;options.KnownNetworks.Clear();options.KnownProxies.Clear();
});
配置中间件:
app.UseForwardedHeaders();
配置Nginx:
proxy_set_header X-Forwarded-Host $host:$proxy_port;
看自己的安排和喜好吧。
05
PART
校验Token
果然不出意外,报错了,是在Admin项目发起登录,获取token后,一直刷新,不能获取资源服务器的API,一直401,解析token查看,缺少字段:
大家可以看到,左侧迁移后的Token令牌竟然少了几个关键Claims,一定是哪里没有配置,
这里先大胆猜测下,我们能登录,证明用户系统没问题;
我们可以获取token,证明客户端Clients配置没问题;
但是一直401,缺少字段,那肯定是我们的资源服务确实对应的scope。
然后我各种检查,发现都是一样的数据,最后我想到了文章上边说到的官方除了增加几个字段以外,还增加了两个表,然后找了找资料,发现4x版本已经更新了,以前的时候,我们只需要针对客户端配置资源api就行了,比如这样:
但是如果你看一下刚刚新建的数据库,可以发现ApiScopes表已经没有了ApiResources表的外键了,所以需要在新增的表ApiResourceScopes中进行配置:
相当于做了一个跳板,当然你也可以说做了一个更复杂的关系表,因为这样的话,我们就可以针对一个资源服务器做多个Scope鉴权了,比如我们Blog.Core项目,我们可以分成好几个scope来鉴权,就像把一个资源服务器,拆成了多个一样,是不是又高级了!
到了这里,基本就已经迁移完成了,整个过程一个小时,当然你还需要部署什么的,也不难,我建议没有充裕的时间,还是用v3吧,如果自己不想折腾。
参考链接:
1、
https://github.com/IdentityServer/IdentityServer4/issues/4592
2、
https://www.identityserver.com/articles/migrating-your-identityserver4-v3-database-to-identityserver4-v4
3、
https://stackoverflow.com/questions/62713022/dotnet-core-identityserver4-reverse-proxy
4、
https://www.cnblogs.com/xhznl/p/13223964.html
彩蛋(2222):