- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
前面选用了IdentityServer4做为认证授权的基础框架,感兴趣的可以看上篇<微服务下认证授权框架的探讨>,已经初步完成了authorization-code与implicit的简易demo(html+js 在IIS部署的站点),并实现了SSO,本想着将Demo迁移到vue工程是轻而易举,毕竟也没啥东西,最终拿到access_token,存储到store里,跟传统的jwt基本上一样,不出意外,意外总是会发生,不然也没办法水一篇帖子,玩笑归玩笑,如果有理解错误,或者使用不当的地方,欢迎拍砖,以免误人子弟 。
- vue2.0 cli
- .net core 6.0
这里为什么不用vue3,尝试过,最终放弃了,本来就是半吊子的前端水平,vue3里的vite跟ts,极大的增加了学习成本,包升级后一些莫名其妙的bug,特别是vite,一些bug提示对我来说特别陌生与不友好(项目不报错,js控制台报错,好像是兼容之类的问题),总之还是太菜,解决不了,又菜又爱玩 。
- http://localhost:3000/test 测试页面,用来代替原来的登录页,用于保存access_token
- http://localhost:3000/callback 回调页面,用于将code换取access_token
- http://localhost:3000/logout 退出页面,用于清除localStorage缓存
在IdentityServer4里,对于前端工程提供了oidc-client.js这个包,在github开源,不过在2021年左右就停止维护了,这里我收集了两条跟本次吐槽相关的Issues https://github.com/IdentityModel/oidc-client-js/issues/1393 https://github.com/IdentityModel/oidc-client-js/issues/1360 。
吓了一跳,OAuth2.1是个什么玩意?来看看GPT的回答 原来官方还没有这个东西,市面上一些对OAuth2.0拓展或者增强的东西,搞了个OAuth2.1,或许只是一个草案,本次吐槽的坑点就是oidc-client.js里PKCE的使用,PKCE全称是 Proof Key for Code Exchange, 在2015年发布, 它是 OAuth 2.0 核心的一个扩展协议, 所以可以和现有的授权模式结合使用,比如 Authorization Code + PKCE,东西是好东西,但是强制使用,不与之前的OAuth2.0兼容,就要被骂了 。
大白话,就是防止授权码(code)被坏人拦截,而设计的一个拓展协议,坏人拿到了code也换取不了access_token,它的实现过程也非常简单,三两句就能讲明白,就不画图了,直接上代码截图 三个角色,授权服务,前端工程,后端工程 。
- 认证中心登录,回调页面上多了两个参数
code_challenge_method 签名方法 code_challenge 签名 。
- 使用code换取access_token的时候,要多带一个code_verifier(随机生成的一个字符串) 参数,否则兑换失败
code_challenge = code_challenge_method(code_verifier) 。
- 协议约定,如果在认证中心生成code的时候,携带了code_challenge_method与code_challenge,那么在使用code兑换
access_token的时候,必须携带code_verifier
如果这还听不明白,那我举个古代银票防伪的例子 张三去钱庄存银子的时候,跟钱庄做了约定,留下一句暗号(DNF)跟暗号的生成方式(取每个字的首字符)给钱庄,兑换者在用银票换银子的时候,钱庄会检查这张银票有没有跟张三做约定,如果有约定,则按照约定让兑换者提供明文,钱庄用兑换者提供的明文跟张三提供的暗号生成方式,来生成暗号,如果一致则允许兑换银子 银票 = code 暗号 = 签名(code_challenge ) 暗号的生成方式 = 签名方法(code_challenge_method ) 明文 = code_verifier(随机字符串) 。
- PKCE关不了
var config = {
authority: "https://localhost:6201",
...
pkce:false
};
前面Issues有提过,提供了这个配置,但是不生效,总之一定会带上 。
- 回调逻辑存在问题
var userManager = new Oidc.UserManager(config);
userManager.signinRedirectCallback().then(function(user) {
// 登录成功,可以在这里处理登录后的逻辑,例如重定向到首页或显示欢迎信息
console.log('用户已登录:', user);
window.location.href = '/home'; // 重定向到应用的主页
}).catch(function(error) {
// 处理登录失败的情况
console.error('登录失败:', error);
alert('登录过程中发生错误,请重试。');
});
这是oidc-client.js里回调页面的处理,它自动做了处理,但是它绕过后端程序,直接向认证服务发起,这里返回400错误,是因为该客户端必须校验秘钥,我们一般将秘钥存储在后端程序,前端程序请求后端,后端带上客户端秘钥,将请求转发给认证服务,这才是authorization-code标准的认证流程,也相对安全 。
- 相同的版本,在(html+js)站点下,并没有启用PKCE,而在vue-cli工程,默认启用PKCE
这点也是我最郁闷的地方,最开始我怀疑是版本问题导致的,后面我降级到相同的版本,但是结果却还是一样,折腾了好久,依旧没有解决,******* 。
- 后端强行关闭PKCE认证
既然vue-cli工程里发起的获取code,会携带PKCE认证信息,那我在重定向地址里,把这两个参数移除,那就搞定收工了 。
- 啃oidc-client.js源码,翻Issues,看看有没有转机
先看Issues,把问题关键字贴进去搜一下,很遗憾没有找到有用的东西,源码简单的翻了下,也没啥帮助 。
- 逆向oidc-client.js,重写回调页面逻辑
既然我们缺code_verifier,那就去找,打印config.userStore,就找到了,这得感谢作者没有每次都删除该对象,不然可能就真的芭比Q了,知道了位置,我们直接从Localstorage取,然后根据时间戳取最新的那条记录,然后提取出code_verifier 。
function getCodeVerifier() {
const allKeys = [];
const items =[];
for (let i = 0; i < localStorage.length; i++) {
allKeys.push(localStorage.key(i));
}
const pattern = /^oidc\./;
const oidcKeys = allKeys.filter(key => pattern.test(key));
for(let i =0;i< oidcKeys.length;i++){
const str = localStorage.getItem(oidcKeys[i]);
if(str != null && str != ''){
const model = JSON.parse(str);
if(model.created == '' || model.created == null || model.created == undefined){
continue
}
items.push(model)
localStorage.removeItem(oidcKeys[i])
}
}
const item = items.reduce((nearest, current) => {
return (nearest.created > current.created) ? nearest : current;
});
return item.code_verifier;
}
最终效果 。
最后此篇关于oidc-client.js踩坑吐槽贴的文章就讲到这里了,如果你想了解更多关于oidc-client.js踩坑吐槽贴的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我遇到了一个错误,我不知道如何解决。我有以下代码(来自 Eliom Graffiti 教程),我正在尝试使用 make test.byte 进行测试。 open Eliom_content.Html5
我阅读文档的理解是这样的: 客户端是测试用例的子类。当我们运行 manage.py test 时,会为每个以“test_”开头的方法创建一个 SimpleTest 类的实例(它继承自 TestCase
我已经编写了一个用于接收多个客户端的服务器,它可以分别与客户端通信。在这里,我可以列出服务器中已连接的客户端,但是当客户端断开连接时,它不会从服务器中删除客户端。 Server.py import s
我正在制作一个社交网站。当任何用户在站点上更新或创建新内容时,我需要查看站点的任何其他用户来查看更改更新。 我有一些需要低延迟的评论,因此建议为此订阅。 我也有事件,但这些不需要这么低的延迟。每 10
我想在突变后使用乐观 UI 更新:https://www.apollographql.com/docs/react/basics/mutations.html 我对“乐观响应”和“更新”之间的关系感到
我想了解 Dask 在本地机器上的使用模式。 具体而言, 我有一个适合内存的数据集 我想做一些 pandas 操作 分组依据... 日期解析 等等 Pandas 通过单核执行这些操作,这些操作对我来说
我使用 Apollo、React 和 Graphcool。我有一个查询来获取登录的用户 ID: const LoginServerQuery = gql` query LoginServerQ
在本指南的帮助下,我最近在几个设备的应用程序中设置了 P2P 通信:http://developer.android.com/training/connect-devices-wirelessly/n
注意:我在节点项目中使用@twilio/conversations 1.1.0 版。我正在从使用可编程聊天过渡到对话。 我看到对 Client.getConversationByUniqueName
我对服务客户端和设备客户端库有点困惑。谁能解答我对此的疑问。 问题:当我通过 deviceClient 发送数据时,我无法接收数据,但当我使用服务客户端发送数据时,相同的代码可以工作。现在,xamar
我对服务客户端和设备客户端库有点困惑。谁能解答我对此的疑问。 问题:当我通过 deviceClient 发送数据时,我无法接收数据,但当我使用服务客户端发送数据时,相同的代码可以工作。现在,xamar
假设我有一个简单的应用程序。 如何设置 OAuth2 以允许其他应用程序访问我的应用程序的某些部分。 例如,当开发人员想要使用 Facebook API 时,他们会使用 Facebook API 用户
我有两个模块: 在一个模块中,我从另一个模块run 中引用了一个函数: @myorg/server import { Client } from '.' import { Middleware } f
我在通过服务器从客户端向客户端发送数据时遇到了一些问题(以避免监听客户端上的端口)。 我有一个这样的服务器: var net = require("net"); var server = net.cr
我正在使用 django.test.client.Client 来测试用户登录时是否显示某些文本。但是,我的 Client 对象似乎并没有让我保持登录状态。 如果使用 Firefox 手动完成,则此测
有两个我制作的程序无法运行。有服务器和客户端。服务器通过给用户一个 ID(从 0 开始)来接受许多客户端。服务器根据服务器的 ID 将命令发送到特定的客户端。 (示例:200 个客户端连接到 1 个服
今天,我在 Windows 10 的“程序和功能”列表中看到了 2 个不同版本的 ARC,因此我选择卸载旧版本,因为我需要一些空间。在卸载结束时,它们都消失了! 所以,我从 https://insta
在每个新的客户端连接上 fork 服务器进程 不同的进程(服务器的其他子进程,即 exec)无法识别在 fork 子进程中使用相同 fd 的客户端。 如何在其他进程上区分客户端? 如果文件描述符为新
a和b有什么区别? >>> import boto3 >>> a = boto3.Session().client("s3") >>> b = boto3.client("s3") >>> a ==
a和b有什么区别? >>> import boto3 >>> a = boto3.Session().client("s3") >>> b = boto3.client("s3") >>> a ==
我是一名优秀的程序员,十分优秀!