每日一博 | 用 Authing 10分钟实现单点登录(SSO)
单点登录(Single Sign On),简称为SSO,是目前比较流行的企业业务整合的解决方案之一。 SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
实现单点登录
开始之前
如果你不了解用户池、单点登录和认证授权,建议先阅读基础概念。
预备知识
- 基本的 HTML 和 CSS 知识
- 中级 JavaScript 技能
所需工具
- 你喜欢的文本编辑器
- 可以在本地运行的 Web 服务器(比如:
npm install http-server -g
)
注册一个 Authing 账号
如果你还没有账号,请点击这里注册 Authing 账号,注册完成后请进入控制台并创建一个用户池。
创建一个 OIDC 应用
第三方登录 -> OIDC 应用选项卡,点击蓝色的「创建 OIDC 应用」按钮。
填上你的应用名,指定此 OIDC 应用的二级域名(认证地址),回调地址,其他参数保留默认即可。点击「确定」。
参数解释
认证地址,一个 authing.cn 的二级域名,用户将在此网址进行登录。
回调 URL,OIDC 登录成功后,回调到开发者自己业务的地址。本教程为演示,填写的地址是 http://localhost:8080,实际场景下要填写自己的业务地址。
在应用列表中点击刚创建好的应用,记录下 AppID,二级域名,供以后使用。
使用 AuthingSSO SDK 集成单点登录
创建一个空白的 HTML 文档用来编写 Authing 程序
本教程只是为了演示,因此我们没选择高级框架,这可以让我们专注于 Authing 本身。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Authing SSO Example</title> </head> <body></body> </html>
添加三个按钮
增加三个按钮控件到 body 中,目的是为了演示如何使用 SDK 管理单点登录状态。
<button id="btn-login">login</button> <button id="btn-track-session">trackSession</button> <button id="btn-logout">logout</button>
引入 AuthingSSO 并初始化
从 CDN 加载 AuthingSSO 的 SDK。填入你的 OIDC 应用 ID 和 域名,进行初始化。
<script src="https://cdn.jsdelivr.net/npm/@authing/sso/dist/AuthingSSO.umd.min.js"></script> <script> let auth = new AuthingSSO({ appId: "YOUR_OIDC_APP_ID", appType: "oidc", appDomain: "OIDC_APP_DOMAIN.authing.cn" }); </script>
为按钮注册点击事件
达到的效果是:
- 点击 login 按钮,浏览器会跳转到 OIDC 登录页面,与用户完成身份确认。
- 点击 trackSession 按钮,会显示当前登录状态。
- 点击 logout 按钮,进行单点登出。
let login = document.getElementById("btn-login"); let trackSession = document.getElementById("btn-track-session"); let logout = document.getElementById("btn-logout"); login.onclick = function() { auth.login(); }; trackSession.onclick = async function() { let res = await auth.trackSession(); alert(JSON.stringify(res)); }; logout.onclick = async function() { let res = await auth.logout(); alert(JSON.stringify(res)); };
完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Authing SSO Example</title> </head> <body> <button id="btn-login">login</button> <button id="btn-track-session">trackSession</button> <button id="btn-logout">logout</button> <script src="https://cdn.jsdelivr.net/npm/@authing/sso/dist/AuthingSSO.umd.min.js"></script> <script> let auth = new AuthingSSO({ appId: "YOUR_OIDC_APP_ID", appType: "oidc", appDomain: "OIDC_APP_DOMAIN.authing.cn" }); let login = document.getElementById("btn-login"); let trackSession = document.getElementById("btn-track-session"); let logout = document.getElementById("btn-logout"); login.onclick = function() { auth.login(); }; trackSession.onclick = async function() { let res = await auth.trackSession(); alert(JSON.stringify(res)); }; logout.onclick = async function() { let res = await auth.logout(); alert(JSON.stringify(res)); }; </script> </body> </html>
示例代码可从 Github 上找到,建议将 Github 上的代码下载运行。
运行方法
在终端中运行以下命令
$ git clone https://github.com/Authing/authing-sso-demo $ cd authing-sso-demo $ npm install -g http-server $ http-server
之后在浏览器访问 http://localhost:8080。
{% hint style="warning" %} 如果本地 8080 端口已被占用,应用可能会运行在 8081、8082 等后续端口。 {% endhint %}
运行效果
最初,我们没有登录,因此,点击 trackSession 按钮获取到的登录状态为空。
现在我们点击 login 按钮,会跳转到 OIDC 应用的用户认证页面,输入用户名密码进行登录。
浏览器被重定向到我们之前设置的回调链接,记下 code 参数,用于后面换取用户信息。
点击 trackSession 按钮,此时能够获取到该用户的登录状态,包括用户 ID,应用 ID,应用类型。
点击 logout 按钮,输出单点登出成功。
此时我们再点击 trackSession 按钮,可见登录状态为空,说明用户已经单点登出了。
获取用户信息
使用 OIDC 流程中返回的 code 换取 access_token
向以下地址发送 POST 请求:
POST https://OIDC_APP_DOMAIN.authing.cn/oauth/oidc/token
body 参数
参数名 | 意义 |
---|---|
client_id | OIDC 应用的 app_id |
redirect_uri | 在控制台配置的 OIDC 回调 url 其中的一个值 |
scope | 需要请求的权限,如果需要获取 email 和手机号需要有 phone email,如果需要 refresh_token 需要包含 offline_access 参考 scope 表格 |
response_type | OIDC 模式,可以为 code, id_token, id_token token, code id_token, code token, code id_token token 参考 OIDC 规范 |
prompt | 可以为 none,login,consent 或 select_account,指定 AP 与 End-User 的交互方式,如需 refresh_token,必须为 consent 参考 OIDC 规范 |
state | 一个随机字符串,用于防范 CSRF 攻击,如果 response 中的 state 值和发送请求之前设置的 state 值不同,说明受到攻击 |
nonce | 一个随机字符串,用于防范 Replay 攻击 |
返回示例
{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InIxTGtiQm8zOTI1UmIyWkZGckt5VTNNVmV4OVQyODE3S3gwdmJpNmlfS2MifQ.eyJqdGkiOiJ4R01uczd5cmNFckxiakNRVW9US1MiLCJzdWIiOiI1YzlmNzVjN2NjZjg3YjA1YTkyMWU5YjAiLCJpc3MiOiJodHRwczovL2F1dGhpbmcuY24iLCJpYXQiOjE1NTQ1Mzc4NjksImV4cCI6MTU1NDU0MTQ2OSwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBvZmZsaW5lX2FjY2VzcyBwaG9uZSBlbWFpbCIsImF1ZCI6IjVjYTc2NWUzOTMxOTRkNTg5MWRiMTkyNyJ9.wX05OAgYuXeYM7zCxhrkvTO_taqxrCTG_L2ImDmQjMml6E3GXjYA9EFK0NfWquUI2mdSMAqohX-ndffN0fa5cChdcMJEm3XS9tt6-_zzhoOojK-q9MHF7huZg4O1587xhSofxs-KS7BeYxEHKn_10tAkjEIo9QtYUE7zD7JXwGUsvfMMjOqEVW6KuY3ZOmIq_ncKlB4jvbdrduxy1pbky_kvzHWlE9El_N5qveQXyuvNZVMSIEpw8_y5iSxPxKfrVwGY7hBaF40Oph-d2PO7AzKvxEVMamzLvMGBMaRAP_WttBPAUSqTU5uMXwMafryhGdIcQVsDPcGNgMX6E1jzLA", "expires_in": 3600, "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InIxTGtiQm8zOTI1UmIyWkZGckt5VTNNVmV4OVQyODE3S3gwdmJpNmlfS2MifQ.eyJzdWIiOiI1YzlmNzVjN2NjZjg3YjA1YTkyMWU5YjAiLCJub25jZSI6IjIyMTIxIiwiYXRfaGFzaCI6Ik5kbW9iZVBZOEFFaWQ2T216MzIyOXciLCJzaWQiOiI1ODM2NzllNC1lYWM5LTRjNDEtOGQxMS1jZWFkMmE5OWQzZWIiLCJhdWQiOiI1Y2E3NjVlMzkzMTk0ZDU4OTFkYjE5MjciLCJleHAiOjE1NTQ1NDE0NjksImlhdCI6MTU1NDUzNzg2OSwiaXNzIjoiaHR0cHM6Ly9hdXRoaW5nLmNuIn0.IQi5FRHO756e_eAmdAs3OnFMU7QuP-XtrbwCZC1gJntevYJTltEg1CLkG7eVhdi_g5MJV1c0pNZ_xHmwS0R-E4lAXcc1QveYKptnMroKpBWs5mXwoOiqbrjKEmLMaPgRzCOdLiSdoZuQNw_z-gVhFiMNxI055TyFJdXTNtExt1O3KmwqanPNUi6XyW43bUl29v_kAvKgiOB28f3I0fB4EsiZjxp1uxHQBaDeBMSPaRVWQJcIjAJ9JLgkaDt1j7HZ2a1daWZ4HPzifDuDfi6_Ob1ZL40tWEC7xdxHlCEWJ4pUIsDjvScdQsez9aV_xMwumw3X4tgUIxFOCNVEvr73Fg", "refresh_token": "WPsGJbvpBjqXz6IJIr1UHKyrdVF", "scope": "openid profile offline_access phone email", "token_type": "Bearer" }
验证 access_token 和 id_token 的合法性
OIDC 默认使用 OIDC 应用的 secret 对 token 进行验证(也就是在创建应用时默认选择 HS256 算法)。 如果你使用 javascript 那么可以使用 jsonwebtoken 进行验证:
const jwt = require('jsonwebtoken'); let decoded = jwt.verify(token, <appSecret>);
如果是其他语言,那么你在服务端需要用 app_secret 作为 HS256 签名参数来计算签名和 JWT 中的签名进行对比,伪代码如下:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), "1133fd20c14e4cc29b6ecb71fb8eb952"// app_secret )
如果是 RS256 等非对称加密算法,需要使用公钥验证签名。Authing 将使用私钥进行签名,请使用 Authing 的公钥来验证签名:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxRijj2seoesv5K0Z+ymR K7DSDPxdsM2sGQD2ZVhLjLsxZWJtXUXh7ERdUU6OT3BqYZZf7CLIhN6yyNtTOgfg pLG9HVJd7ZSKzuy2dS7mo8jD8YRtptAJmNFqw6z8tQp5MNG1ZHqp9isKqJmx/CFY kRdXBmjjj8PMVSP757pkC3jCq7fsi0drSSg4lIxrSsGzL0++Ra9Du71Qe/ODQKU0 brxaI1OKILtfcVPTHTaheV+0dw4eYkSDtyaLBG3jqsQbdncNg8PCEWchNzdO6aaj Uq4wbOzy/Ctp399mz0SGKfuC5S8gqAFABFT3DH3UD21ZztQZwFEV2AlvF+bcGEst cwIDAQAB -----END PUBLIC KEY-----
使用 access_token 换取用户信息
开发者在自己的服务中可以使用 access_token 换取用户信息。根据 scope 的不同,这里的返回信息也会有所不同,字段符合 OIDC 规范,字段解释请参考用户信息字段含义。 请求链接:
GET https://users.authing.cn/oauth/oidc/user/userinfo?access_token=<access_token>
返回示例:
{ "sub": "<用户在 Authing 的唯一标识>", "nickname": "Authing", "name": "张三", "locale": "en-US" }
更多字段解释请参考用户信息字段含义。
接下来你可能还需要
了解 OIDC 协议:
控制台是你管理所有 Authing 资源的地方,了解 Authing 控制台各模块包含的内容和你可以在控制台中做的事情:
了解 Authing 提供的多种部署模型,以帮助你选择该以怎样的形式部署 Authing:
什么是 Authing?
Authing 提供专业的身份认证和授权服务。 我们为开发者和企业提供用以保证应用程序安全所需的认证模块,这让开发人员无需成为安全专家。 你可以将任意平台的应用接入到 Authing(无论是新开发的应用还是老应用都可以),同时你还可以自定义应用程序的登录方式(如:邮箱/密码、短信/验证码、扫码登录等)。 你可以根据你使用的技术,来选择我们的 SDK 或调用相关 API 来接入你的应用。当用户发起授权请求时,Authing 会帮助你认证他们的身份和返回必要的用户信息到你的应用中。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
微软收购 jClarity,以提高 Azure 上 Java 工作负载的性能
微软已经收购了 jClarity,此次收购将通过提高 Java 工作负载的性能来增强微软的 Azure 云计算平台。 jClarity,AdoptOpenJDK 项目的主要贡献者,也是开源的主要贡献者,该公司利用机器学习来查找其 Censum 工具中的内存泄漏,以及其照明诊断引擎的性能问题。 微软的程序管理副总裁 Montgomery 说: 在过去几年里,微软对 Java 的使用有所增长。jClarity 团队在数据驱动的 Java 虚拟机(Jvm)优化方面拥有公认的专业知识,将帮助微软的团队更好地吸收Java 平台的进步。 微软 Azure 和 jClarity 工程师将共同努力,为我们的 Java 客户和内部团队打造一个更好的平台,提高 Java 开发人员和最终用户的体验和性能。我们坚信,通过与 Java 社区一起努力,我们可以为我们的客户做更多的事情。 自 2018 年 6 月以来,微软一直赞助 AdoptOpenJDK 项目,目的就是帮助为 Linux 和 Windows 等平台构建 OpenJDK 的二进制文件。OpenJDK 是 Java 平台标准版(Java Platfo...
- 下一篇
开源持续交付黑客松,欢迎你来挑战!
黑客松编程比赛开启报名,巅峰对决,等你来战! 你是否希望与顶尖编程高手同场较量,是否想体验创意与技术的碰撞?黑客松编程比赛释放你的激情,满足冠军梦想。 黑客松编程比赛报名正式拉开帷幕。本次赛事以 DevOps 为主题集结研发、测试、运维、产品、文档、HR等各路人马,秉承开源开放的方式,旨在为各个行业面临的 IT 挑战提出解决方案,鼓励人人参与开源社区,展现开源之魅力。 本次比赛为期两天,由 Jenkins 中文社区联手 CloudBees、京东云、阿里云、码云、开源社和微软组织承办。选手要在48小时内根据所选议题设计解决方案,在有限的时间内激发无限创意想法。 比赛规则 活动中创建的新代码仓库均在码云上的 Jenkins 中文社区进行托管,任何人都可以根据对应开源协议进行修改、分发等操作。 所有代码工作(包括文档、设计等)必须当场完成。若提前准备或抄袭,一经发现,将取消当年及次年的比赛资格。 所有项目必须可以做到持续构建,持续交付和灰度发布则为加分项。 推荐与不同技能的小伙伴组建3人左右的团队,一起完成项目。 评选标准 团队协作、完整性、创新程度、难易程度、大众评分 报名方式 本次比赛通...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Red5直播服务器,属于Java语言的直播服务器
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS关闭SELinux安全模块
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7设置SWAP分区,小内存服务器的救世主