单点登陆
概念: 单点登录其实就是在多个系统之间建立链接, 打通登录系统, 让同一个账号在多个系统中通用
举个例子: 登录Gmail的时候可以用账号密码登录, 也可以用google账号登录, 而使用google账号登录就是这里的单点登录
下面我将记录一下我们系统集成明道云(低代码平台)的单点登录功能
单点登录流程图
1. 集成明道云的单点登录功能
这是开发文档(虽然写的比较烂)
https://docs.pd.mingdao.com/faq/sso/oauth
有几个比较恶心的点
- 挂载配置文件
sso.json
, 这个配置文件一定要配置好, 否则后患无穷
-
另外还有一个就是几个请求的入出参数, 这两个请求都是需要在自己系统开发, 提供给明道云调用
- /access_token
- /userInfoUrl
-
另外可以去私有化部署后台查看错误日志, 搜索sso
至此, 明道云算是集成完成, 这是我在本地测试环境下配置的sso.json
2. 本地测试环境搭建
这里我用flask搭建了一个测试平台, 对接第三方Github的oauth2单点登录, 如何去对接第三方github测试平台可以参考下面的文档
https://blog.csdn.net/CSDN2497242041/article/details/120416969
这里后端的思路(这里提供的后端接口都要和配置文件相对应):
- /login 接收明道云跳转到本地的地址
- /callback 对接第三方Github的回调地址(返回时会携带授权码code)
- /access_token 提供给明道云获取token的接口
- /getUserInfo 提供给明道云获取用户信息的接口
3. 本地测试源码
这些都是本地测试的情况下, 故很多数据是模拟的
python
from flask import Flask, request, redirect, url_for, jsonify
from oauthlib.oauth2 import WebApplicationClient
import requests
app = Flask(__name__)
# 定义OAuth2客户端配置
client_id = 'd0477fd462f8cc3a22a'
client_secret = 'be3c5c91d0d67c92217c9a20674749e316d9c11'
authorization_endpoint = 'https://github.com/login/oauth/authorize'
token_endpoint = 'http://106.15.59.77:8880/orgsso/oauth2'
redirect_uri = 'https://ae50-180-164-83-69.ngrok-free.app/callback' # 替换成你的后端服务器的回调URL
client = WebApplicationClient(client_id)
access_token = "kl34j23kl4j23lk4jkl23" # kl34j23kl4j23lk4jkl23
USER_INFO = {
"uid": "112", # 111, 112
"name": "帅哥",
"email": "nbaba@qq.com",
"mobilePhone": "11111111111",
"positions": ["职位1", "职位2"],
"departments": ["部门1", "部门2"]
}
# 启动OAuth2认证流程
@app.route('/login')
def login():
username = request.args.get("username")
password = request.args.get("password")
USER_INFO['name'] = username
# 创建OAuth2授权请求 -> github
authorization_url, state, _ = client.prepare_authorization_request(
authorization_endpoint,
redirect_url=redirect_uri
)
print(authorization_url)
return redirect(authorization_url)
# 处理OAuth2回调
@app.route('/callback')
def callback():
# 获取授权码
code = request.args.get('code')
print(code)
# 到github中获取access_token
# access_token_url = "https://github.com/login/oauth/access_token?code=%s&client_id=%s&client_secret=%s" % (
# code, client_id, client_secret)
# resp = requests.get(access_token_url)
# access_token = resp.text.split("&")[0].split('=')[-1]
# print(access_token)
# getUserInfo_url = "https://api.github.com/user?access_token=%s" % access_token
# headers = {
# "Authorization": "token %s" % access_token
# }
# resp = requests.get(getUserInfo_url, headers=headers)
# print(resp.text)
# 使用授权码请求访问令牌
token_url = "http://106.15.59.77:8880/orgsso/oauth2"
# params = {
# "code": code
# }
# token_response = requests.get(token_url, params=params)
# print(token_response, token_response.text)
return redirect(token_url + "?code=%s" % code)
@app.route('/access_token', methods=['POST'])
def token():
data = {
"access_token": access_token,
"expires_in": 7200
}
print(data)
return jsonify(data)
@app.route('/getUserInfo', methods=['GET'])
def get_user_info():
response = {
"data": USER_INFO
}
return jsonify(response)
if __name__ == '__main__':
import os
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
app.run(debug=True)
4. 前端代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<link rel="stylesheet" href="bootstrap-3.4.1-dist/css/bootstrap.min.css">
<script src="bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form action="http://106.15.59.77:8880/orgsso/sso?returnUrl=http://106.15.59.77:8880/app/my">
<h1 class="text-center">这是Linkda的主站</h1>
<p>
<label for="username">username:</label>
<input type="text" class="form-control" name="username" id="username">
</p>
<p>
<label for="password">password:</label>
<input type="password" class="form-control" name="password" id="password">
</p>
<p>
<input type="submit" value="登录" class="btn btn-primary btn-block">
</p>
</form>
</div>
</div>
</div>
</body>
</html>
从最上面的思路流程图中我们可以看出来, 前端最主要的是点击提交后我们跳转的地址是http://106.15.59.77:8880/orgsso/sso?returnUrl=http://106.15.59.77:8880/app/my
, 而这个地址会由明道云转发到本地的/login, 再进行后续操作
5. 单点登录效果
-
前端登录界面点击登录
-
跳转到后台, 且获取github授权码
-
携带code发送到明道云之后, 明道云会发两个请求 /access_token /getUserInfo 获取到用户信息就是单点登录成功
- 这是后台接收日志
- 会根据ReturnUrl跳转到明道云界面, 此时单点登录完成
补充:
1. 服务器如何访问本地测试地址
相信看到这里, 会有很多人问: 你后台明明是测试环境, 为什么地址是这玩意儿
"oauth2Url": "https://ae50-180-164-83-69.ngrok-free.app"
这其实就涉及到一个内网穿透的问题, 为了方便测试, 没问在本地搭的服务也就是127.0.0.1:5000
在明道云私有部署的服务器之间肯定是无法访问的, 那么我们就需要去借助一个工具Ngrok将本地地址暴露到公网上, 让服务器能访问到, 这个工具的功能就类似于代理
使用起来也比较简单, 直接点击ngrok.exe文件, 在终端输入命令
ngork http 5000
# 5000可以换成本地的其他端口
此时Forwarding后面就是暴露到公网的地址
我们可以在明道云的服务器上测试, 如果又返回, 说明暴露成功
curl -X POST https://ae50-180-164-83-69.ngrok-free.app/access_token
注意: 此时的网址, 当出现302跳转的时候还是会报错, 这需要我们登录ngrok账号, 拿到Authtoken且执行以下命令才可以完成302redirect
ngrok config add-authtoken 2WvKgyYxeIpT3wyToJOwNEwXbkF_47CPhYhHcTKnyNv5qw81D
2.不使用第三方Github实现oauth2
oauth2只是一个协议, 我们可以跟着官网的规范来, 在自己的系统中跟着流程搭建自己系统的oauth2服务, 自己搭建服务有两个好处
- 第三方Github链接不稳定, 反应迟钝用户体验感差
- 使用Github第三方会出现授权界面(Authorize), 这样会对有自己品牌的系统产生影响(你懂的)
后面我会继续跟新关于我们系统集成oauth2授权的相关思路