Python Flask快速与XAuth集成
本教程将介绍如何使用 XAuth 的统一身份验证服务,它能让我们在 Python 项目中轻松处理用户数据。
本节介绍如何使用Python Flask快速与XAuth集成,将XAuth作为WEB应用程序的用户存储库并实现用户登录。
准备工作
本教程使用了 Python3.x 版本构建程序,所以请留意各项依赖包的版本。
- Flask
- Flask-OIDC
- XAuth SDK
- 一个免费的 XAuth 账户
- 已有或新建的Web应用程序或项目,或可使用本教程代码示例 XAuth Python Example,基于MIT协议,可以免费/商业使用。
安装依赖
首先我们使用 venv 创建一个干净的开发环境,并激活该环境
python3 -m venv flaskXAuth
source ./flaskXAuth/bin/activate
接下来利用 pip 安装所需的依赖
pip install flask>=2.0.2 flask-oidc>=1.4.0
安装成功后,我们安装了所需的 Flask 和 XAuth 依赖项,让我们开始构建 Flask 应用
创建一个 Flask 应用
我们创建一个名字为 flaskapp 的项目目录,然后创建一个名为 app.py 的文件,包含下面的代码
# imports for Flask
from flask import Flask, Response
app = Flask(__name__)
@app.route("/protectme")
def protect_me():
return Response("I should be protected!")
@app.route("/")
def landing_page():
return Response("I am open for any visitors")
接下来我们可以使用以下命令运行这个 Flask 应用程序
set FLASK_APP=app.py
flask run
在 Web 浏览器中访问 http://localhost:5000,您应该看到
现在转到 http://localhost:5000/protectme 看看。这个页面应该需要身份验证才能访问,但现在它似乎没有任何保护
但可以确定的是,我们的基础应用已启动并运行,下面让我们为它增加身份验证功能
创建 XAuth 开发者账户
访问打开注册页面
输入表单信息后提交,会提示输入验证码,以确保你没有输错Email地址。此时需要查收你的Email,找到类似的邮件
然后继续输入你接受到的验证码后,会提示创建成功,再回到你的邮箱,查看用户激活邮件
点击激活,会提示设置管理员密码。设置好之后,用你的Email登录。会看到管理员面板
可以看到浏览器地址栏标记黄色的部分,就是你的租户地址了,不仅仅可以通过这个地址访问到管理面板,而且后续我们会用到这个地址配置协议参数。
连接应用到 XAuth
我们接下来要在 XAuth 上创建一个应用。我们选择左侧菜单的【应用】然后在面板右侧点击【创建应用】
我们会看到创建应用的弹出框:
我们在这里认证方式选择 OIDC,应用类型选择 Web 应用,点击下一步:
我们创建一个应用名为 flaskapp 的应用,将 http://localhost:5000/oidc/callback 作为登录重定向的地址。
接下来,我们会看到创建好的应用信息(请留意黄色标记部分):
⚠️特别步骤:我们需要增加一个安全域,CORS防止调试时被浏览器拦截,点击左侧菜单【API】选择【安全域】
然后点击右侧的【添加域】根据下面的图示输入:
配置并保护相关 URI
很好,到此我们已经获取到了必要的参数了。接下来我们创建一份 OIDC 客户端配置,创建文件 openidconnect_secrets.json 输入:
{
"web": {
"client_id": "",
"client_secret": "",
"auth_uri": "/oauth/v1/authorize",
"token_uri": "/oauth/v1/token",
"issuer": "/oauth/v1",
"userinfo_uri": "/oauth/v1/userinfo",
"redirect_uris": [
"http://localhost:5000/oidc/callback"
]
}
}
需要将双括号的变量替换为已经获取到的参数,完整如下:
{
"web": {
"client_id": "7Bluj051DFz63z6E0258p3h8dv9Kzva4",
"client_secret": "Dt934T3427EwzvGd3Z2gJ5o14D0061mRF66i1F9T435G85aA",
"auth_uri": "https://yourdomain.xauth.cloud/oauth/v1/authorize",
"token_uri": "https://yourdomain.xauth.cloud/oauth/v1/token",
"issuer": "https://yourdomain.xauth.cloud/oauth/v1",
"userinfo_uri": "https://yourdomain.xauth.cloud/oauth/v1/userinfo",
"redirect_uris": [
"http://localhost:5000/oidc/callback"
]
}
}
⚠️请注意:实际使用过程中 URL 值与本文例子是不同的,需多加留意。
我们增加一些代码,读取配置:
# imports for Flask
from flask import Flask, Response
from os import environ
from flask_oidc import OpenIDConnect
app = Flask(__name__)
# secret credentials for XAuth connection
app.config["OIDC_CLIENT_SECRETS"] = "openidconnect_secrets.json"
app.config["OIDC_COOKIE_SECURE"] = False
app.config["OIDC_CALLBACK_ROUTE"] = "/oidc/callback"
app.config["OIDC_SCOPES"] = ["openid", "email", "profile"]
app.config["SECRET_KEY"] = environ.get("SECRET_KEY")
app.config["OIDC_ID_TOKEN_COOKIE_NAME"] = "oidc_token"
# instantiate OpenID client to handle user session
oidc = OpenIDConnect(app)
# client will determine if a user has an appropriate account
XAuth_client = Client(environ.get("XAuth_TENANT_URL"),
environ.get("XAuth_AUTH_TOKEN"))
@app.route("/protectme")
def protect_me():
return Response("I should be protected!")
@app.route("/")
def landing_page():
return Response("I am open for any visitors")
我们新增加了4、5行以引入依赖的包。第10行至20行,我们将 openidconnect_secrets.json 的配置引入到 Flask应用中。新代码的其余部分设置 Flask 应用的配置值,可用于实例化 OpenID Connect。
到此,我们的基础设置已经搞定了,但保护相关的资源还需要我们添加代码声明一下:
# imports for Flask
from flask import Flask, Response
from flask import redirect, g, url_for
from os import environ
from flask_oidc import OpenIDConnect
app = Flask(__name__)
# 连结到 XAuth 服务的Flask参数设置
app.config["OIDC_CLIENT_SECRETS"] = "openidconnect_secrets.json"
# 必须在生产环境中将此设置为 True
app.config["OIDC_COOKIE_SECURE"] = False
# Web应用中用于处理用户登录的 URL
app.config["OIDC_CALLBACK_ROUTE"] = "/oidc/callback"
# 用户登录时要请求的有关用户的数据,此处我们要求提供基本的电子邮件、姓名和个人资料信息
app.config["OIDC_SCOPES"] = ["openid", "email", "profile"]
# 这是一个 Flask 设置,用于确保会话安全,绝不能公开它
app.config["SECRET_KEY"] = environ.get("SECRET_KEY")
app.config["OIDC_ID_TOKEN_COOKIE_NAME"] = "oidc_token"
oidc = OpenIDConnect(app)
@app.before_request
def before_request():
"""实现检查用户是否在每次请求之前登录过"""
if oidc.user_loggedin:
g.user = oidc.user_getfield("sub")
else:
g.user = None
@app.route("/protectme")
@oidc.require_login
def protect_me():
return Response("I should be protected!")
@app.route("/")
def landing_page():
return Response("I am open for any visitors")
@app.route("/login")
@oidc.require_login
def login():
return redirect(url_for(".protectme"))
@app.route("/logout")
def logout():
oidc.logout()
return redirect(url_for(".landing_page"))
我们又在第二行添加了 Flask 相关方法,以完成我们的保护功能。24行-30行,实现检查用户是否在每次请求之前登录过。
如果路由由于 @oidc.require_login 装饰器而需要登录用户,则用户将被重定向到登录页面。我们还在 /login 和 /logout 下添加了路由,使登录和退出我们的应用成为可能。
在命令行运行下面的指令,设置环境变量:
# this tells Flask we want to run the built-in server in dev mode
export FLASK_ENV=development
# make sure to use a very long random string here that cannot be guessed
export SECRET_KEY='a very long string with lots of numbers and letters'
然后在这个命令行终端中重新运行我们的 Flask 应用:
set FLASK_APP=app.py
flask run
运行起来后,当我们尝试通过访问 http://localhost:5000/protectme 转到 /protectme 路由时,让我们测试重定向功能,此时我们应被重定向到 XAuth 登录页面:
输入你的 XAuth 开发者用户名和密码以登录你的 Flask 应用。一切顺利的话,你会看到跳转到路由后显示的信息:
到此,对接成功了!
之后当你输入 http://localhost:5000/logout 时会取消对你的用户的身份验证,此时再次访问 /protectme 又会跳转到认证的界面重新认证。
⚠️请注意:出于开发目的,这仅适用于测试。但在生产应用程序中,你需要创建其他帐户供用户登录。
总结
我们通过 Flask 构建了一个简单的应用,利用Open ID Connect 协议并对接 XAuth 提供的身份服务,实现了保护我们特定路由的方法。