• NoName Blog
  • 搜索
导航
  • 首页
  • 统计
  • 关于
  • 友链
  • 朋友圈
  • 写作
分类
标签
文章
Csharp操作
关于我是怎么完成 SSO (单点登录)的这档事

© 2026 NoName Blog. All rights reserved.

开往GitHub RepoRSSSitemap萌ICP备20260063号
2025年12月29日·14 min read

关于我是怎么完成 SSO (单点登录)的这档事

因为很多原因,社团需要写一个单点登录,最好是可以让大部分开源项目也能用上。于是我盯上了 OAuth 2 / OIDC...

分类: Csharp操作#SSO#CSharp

众所周知,iOS Club 现在有了越来越多的网站,但是我们还没有一个统一的登录接口。之前我倒是想过把社团官网当数据源,看能不能接入 Casdoor/Logto 这种 sso 平台,但很明显不行。于是自从官网重构以来,我都一直在想着能不能搞个专门的平台来搞定这件事。于是这就来了。

SSO是什么

SSO(单点登录),其实可以说是一种非常常见的登录方式,例如建大的统一身份认证平台,或者游戏里常出现的 微信/QQ 登录,都是 SSO 的操作 —— 让登录变成一个专门的事情,用一个登录接口来管理所有系列的登录事宜。这种登录方式说实话还是很方便的,至少可以不用记那么多密码,登录起来也方便的很。

所有对于 SSO 来说,玩的更多是跳转的艺术:先跳转到统一登录平台,然后再跳转回去,登录完了再拿个能够证明你是你的令牌。

所有关键变成了,我们该怎么进行身份验证,以及我们该怎么跳转。

我们该怎么去进行身份验证

从底子上就是,你现在要去申请一个身份证,得先去派出所,然后先验证一下你是不是你(通过对照数据库的数据来进行查找,判断你是不是你),证明成功之后给你颁发一个身份证(返回一个 token)。之后你就可以用这个身份证去干一些需要证明身份的事情了。

所以关键就在于如何去判断你是你、如何去生成这个 Token,以及如何去携带。

从判断来说的话,最简单的方式就是直接把用户名密码给写到 token 里,然后等到需要验证的时候,再来一次服务器查找就行了。

但是很明显这种方法太抽象了:一旦被其他人“截胡”了,就算你用 Base64,人一解析立马就能把你用户名和密码给套出来。

所以最好的办法就是,咱们“随机生成”一个 Token,然后把这个 Token 存到数据库里,然后当你每次进行验证的时候,就跑到数据库对比一下 Token 即可。

我们可以写一个这样的:将用户 ID + 随机 UUID + 时间 UTC 进行字符串合并,然后再进行加密即可。当然这样就必须让接口加入一个用户 ID 的接入:因为数据库需要查到他。

当然,任何的 Token 都应该有时间限制,要不然迟早都会被其他人拿走用来做坏事。

但是啊,有没有一种操作,我们可以把这种 Token 结构化,就像咱们的身份证号码一样,可以从号码中得到你的户籍地,生日信息。咱们也可以让 Token 存入 用户 Id,时间限制等信息。这种结构必须是一种可以被解析的,也可以扩展的。没错,用 Json。

让 Json 来存身份验证信息 —— JWT

Json 这个东西,先给各位看看 Json 长什么样子吧:

JSON
{
 "name": "LuckyFish",
 "hash": "asdfasdflkjajksbhdfoiuasgf",
 "time": 12309719837
}

这东西其实和 JS 的 Object 长得很像了,当然事实上 Json 的全称就是JavaScript对象表示法(JavaScript Object Notation)。用这东西来存结构化数据最好不过了。

那么把 Token 和 Json 一结合,再加上这东西主要用于 Web,于是就出现了 Json Web Token,也就是 JWT。

JWT其实分为三部分:Header(头部)、Payload(荷载) 和Signature(密钥)。第一个部分主要用来声明用何种哈希算法,第二个部分则是用来存储各种数据的:例如用户 ID、过期时间等,第三个部分则是签名,这个部分通常为头部、荷载与一个密钥产生的哈希值。这样的话可以最大限度的保证安全。当然你要是把密钥给泄露了那就好玩了。

这里也简单推荐一个随机生成密钥的网站:就是这个

当然如果担心密钥给泄露了,也可以加入一个简单的:在荷载中加入一个 UUID 值。这样整个密钥就彻底独一无二了。

目前来说社团官网的登录系统和 OAuth2/OIDC 系统就是用的 JWT。因为这个可以加入很多的荷载,从而完成很多操作(虽然也不推荐存太多东西)。当然事实上我也没学过其他的 Token 生成方式

从携带来看分两种:Cookie 和 Authorization:

Cookie

Cookie 其实用的蛮多的。这个的原意是服务器向客户端(浏览器)发送的一种小型信息文件,而浏览器也会进行存储,并把这些东西当随身物品自动附加到每次请求中。

于是就有人发现这东西当身份验证刚刚好 —— 浏览器自动帮你附加。于是就有人会这么干:当登录操作结束的时候,会把登录信息的令牌放到 Cookie 里,直接传给前端。浏览器就会自动存储,然后之后的所有请求上都会加上这个信息。

Authorization

这种和前面的 Cookie,其实都在请求头上,但是这个得你自己设置。在前端上一般这么设置:

TypeScript
const response = await fetch(url, {
        headers: {
            Authorization: `Bearer ${token}`,
        },
});

得你自己手动设置一下。但是这个的好处就在于你完全可以自己定义,这个验证或者不验证取决于前端人员。这种就叫做无状态。这种的好处就在于利于分布式系统(因为不依赖于某个服务器和客户端的会话)

OAuth2 到底是个啥

在了解了身份验证和令牌的基础知识后,我们现在可以回到最初的问题:如何设计一个安全、通用的跳转流程来实现 SSO。这正是 OAuth2 框架要解决的核心问题。

我们可以先思考一个简易的通用登录系统:

直接在第三方网站中写个类似的登录接口,然后就像模拟官网登录一样,调用官网登录 API,这之后就可以得到一个 Token 记录,然后验证成功之后就 OK 了。

但是很明显,当我想要获取到官网的其他数据时,就需要记录用户名和密码。此时就会出现泄露问题,而且还有一个更大的问题 —— 万一我官网登录发生了改变,就例如从用户名密码变成了手机号密码呢?此时第三方应用的前端和后端就得更改。

那么最好的办法就是重定向到官网接口,然后再从官网接口重定向回来,此时就可以携带相应的 Token 了。

现在我们可以设计一个跳来跳去的方法:

  1. 先访问 API接口,携带一个客户端 ID
  2. API 重定向到通用的前端接口
  3. 登录成功后携带着 token 重定向回第三方应用

这个其实也就是 OAuth 2 的基本操作了,但就是会麻烦一些。

说实话,OAuth2 的方案其实很多,但是我只讲一个我认为最安全的方案。

Authorization Code 授权码

根据我们上面的想法,我们可以结合一下:

  1. 在第三方网站点击“SSO 登录”。此时访问 SSO 的 authorize 接口(这个接口一般就叫authorize这个名字),同时携带:
    • response_type:表示授权类型,必选项,此处的值固定为"code"
    • client_id:表示客户端的ID,必选项
    • redirect_uri:表示重定向URI,可选项
    • scope:表示申请的权限范围,可选项
    • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
  2. SSO 的 authorize 会重定向到 SSO 的登录页面。然后用户身份验证成功(并同意授权)后,系统会生成一个临时的 授权码 (Authorization Code)。
  3. 后端将浏览器重定向回第三方应用的回调地址,并附带授权码和最初的 state 参数
  4. 第三方应用拿到 code 后,通过后台向 SSO 平台发起请求以换取真实令牌(access_token)。这个接口一般是 /token
    • grant_type=authorization_code
    • code
    • client_id:客户端 Id
    • client_secret:客户端密钥
    • redirect_uri:回调 URL
  5. 拿到access_token之后,一般还要拿用户的数据。这里需要使用到最开始给的那个scope,根据scope和access_token进行拿取。这个接口一般是 /userinfo
Mermaid 图表加载中...

我感觉还是看图会稍微能看懂点

到此为止其实已经结束了。说实话其实还是有点复杂的。但是这里面很明显就变得很安全了 —— 例如这里在过程中使用了两个钥匙:code 和 state。这两个钥匙并不是

许可协议
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 许可协议,转载请注明出处。

上一篇

全文搜索?直接上 PGSQL!

下一篇

还不知道怎么去选择项目的技术栈?速来看看这个!

评论

目录

  • SSO是什么
  • 我们该怎么去进行身份验证
  • 让 Json 来存身份验证信息 —— JWT
  • Cookie
  • Authorization
  • OAuth2 到底是个啥
  • Authorization Code 授权码