如何使用 Ory Kratos 和 Ory Keto 保护您的烧瓶应用程序
如今,工程界在其框架中有许多用于身份验证的产品。它们中的许多具有用于身份验证的内置功能以及许多可用于社交登录的库。我们有 Django 框架、Flask 和 python-social-auth 来构建我们在 pythonic 世界中对用户进行身份验证所需的几乎所有东西。 在本文中,我将向您展示如何在不编写大量代码的情况下添加用户身份验证所需的所有内容的示例。本博文中使用的代码可在GitHub上找
如今,工程界在其框架中有许多用于身份验证的产品。它们中的许多具有用于身份验证的内置功能以及许多可用于社交登录的库。我们有 Django 框架、Flask 和 python-social-auth 来构建我们在 pythonic 世界中对用户进行身份验证所需的几乎所有东西。
在本文中,我将向您展示如何在不编写大量代码的情况下添加用户身份验证所需的所有内容的示例。本博文中使用的代码可在GitHub上找到。我们将使用烧瓶,烧瓶饼干切口,docker,[docker-compose]222222[
让我们看一下使用 Ory Kratos 和 Ory Keto 的应用程序的登录流程。
![](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%27800%27%20height=%27585%27/%3e)
<img altu003d"使用 Ory Kratos 和 Keto 保护 Flask 应用程序的图表" srcsetu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2Fcl-07-wd-9- fx-00-f-70-bs-65-r-7-q-77-db.jpg&wu003d828&qu003d75 1x, /_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages %2Fcl-07-wd-9-fx-00-f-70-bs-65-r-7-q-77-db.jpg&wu003d1920&qu003d75 2x" srcu003d"/_next/image?urlu003dhttps %3A%2F%2Fcdn.hackernoon.com%2Fimages%2Fcl-07-wd-9-fx-00-f-70-bs-65-r-7-q-77-db.jpg&wu003d1920&qu003d75" 解码u003d"async" data-nimgu003d"intrinsic" styleu003d"position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none; margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:contain"类u003d“图像”加载u003d“懒惰”>
使用 Ory Kratos 和 Keto 保护 Flask 应用程序的示意图
我们将在我们的项目中使用什么
-
Flask cookiecutter是引导我们项目结构的好工具。开箱即用的 linters、Dockerfile 和包管理工具总是一个好主意。
-
Postgres 作为 RDBMS。在本例中,我们将在两个容器中运行两个 Postgres 服务。我认为保持简单而不使用自定义脚本在单个 docker-compose 服务中提供多个数据库是一个好主意。
-
Ory Kratos 使用 UI 对用户进行身份验证。
-
Ory Keto 作为访问控制服务。
设置 Ory Kratos
Ory Kratos 将负责存储身份数据,例如电子邮件/登录名和密码。使用quickstart指南,我们需要将contrib/quickstart/kratos/email-password的内容复制到项目的根目录,然后将以下内容添加到 docker-compose:
postgres-kratos:
image: postgres:9.6
ports:
- "5432:5432"
environment:
- POSTGRES_USER=kratos
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=kratos
networks:
- intranet
kratos-migrate:
image: oryd/kratos:v0.8.0-alpha.3
links:
- postgres-kratos:postgres-kratos
environment:
- DSN=postgres://kratos:[email protected]:5432/kratos?sslmode=disable&max_conns=20&max_idle_conns=4
networks:
- intranet
volumes:
- type: bind
source: ./kratos
target: /etc/config/kratos
command: -c /etc/config/kratos/kratos.yml migrate sql -e --yes
kratos:
image: oryd/kratos:v0.8.0-alpha.3
links:
- postgres-kratos:postgres-kratos
environment:
- DSN=postgres://kratos:[email protected]:5432/kratos?sslmode=disable&max_conns=20&max_idle_conns=4
ports:
- '4433:4433'
- '4434:4434'
volumes:
- type: bind
source: ./kratos
target: /etc/config/kratos
networks:
- intranet
command: serve -c /etc/config/kratos/kratos.yml --dev --watch-courier
kratos-selfservice-ui-node:
image: oryd/kratos-selfservice-ui-node:v0.8.0-alpha.3
environment:
- KRATOS_PUBLIC_URL=http://kratos:4433/
- KRATOS_BROWSER_URL=http://127.0.0.1:4433/
networks:
- intranet
ports:
- "4455:3000"
restart: on-failure
mailslurper:
image: oryd/mailslurper:latest-smtps
ports:
- '4436:4436'
- '4437:4437'
networks:
- intranet
postgres-keto:
设置 Ory Keto
您可以阅读快速入门指南来熟悉 Ory Keto 的概念。这些文章可以给你一个简单的介绍。由于我们需要管理对主页的访问权限,因此我们需要在项目的根目录下创建一个文件夹keto
,并拥有一个包含以下内容的keto/keto.yml
文件:
version: v0.7.0-alpha.1
log:
level: debug
namespaces:
- name: app
id: 1
serve:
read:
host: 0.0.0.0
port: 4466
write:
host: 0.0.0.0
port: 4467
我们需要以下容器:
-
postgresd-auth 是 Ory Keto 的数据库。
-
keto-migrate 负责数据库迁移。
-
keto-perms 是一个使用命令行界面处理权限的包装器。
-
keto 运行服务器。
version: "3.7"
x-default-volumes: &default_volumes
volumes:
- ./:/app
- node-modules:/app/node_modules
- ./dev.db:/tmp/dev.db
services:
oathkeeper:
image: oryd/oathkeeper:v0.38
depends_on:
- kratos
ports:
- 8080:4455
- 4456:4456
command:
serve proxy -c "/etc/config/oathkeeper/oathkeeper.yml"
environment:
- LOG_LEVEL=debug
restart: on-failure
networks:
- intranet
volumes:
- ./oathkeeper:/etc/config/oathkeeper
flask:
build:
context: .
image: "kratos_app_example-development"
environment:
- FLASK_APP=autoapp.py
- FLASK_ENV=development
networks:
- intranet
restart: on-failure
volumes:
- type: bind
source: ./
target: /app
postgres-kratos:
image: postgres:9.6
ports:
- "5432:5432"
environment:
- POSTGRES_USER=kratos
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=kratos
networks:
- intranet
kratos-migrate:
image: oryd/kratos:v0.8.0-alpha.3
links:
- postgres-kratos:postgres-kratos
environment:
- DSN=postgres://kratos:[email protected]:5432/kratos?sslmode=disable&max_conns=20&max_idle_conns=4
networks:
- intranet
volumes:
- type: bind
source: ./kratos
target: /etc/config/kratos
command: -c /etc/config/kratos/kratos.yml migrate sql -e --yes
kratos:
image: oryd/kratos:v0.8.0-alpha.3
links:
- postgres-kratos:postgres-kratos
environment:
- DSN=postgres://kratos:[email protected]:5432/kratos?sslmode=disable&max_conns=20&max_idle_conns=4
ports:
- '4433:4433'
- '4434:4434'
volumes:
- type: bind
source: ./kratos
target: /etc/config/kratos
networks:
- intranet
command: serve -c /etc/config/kratos/kratos.yml --dev --watch-courier
kratos-selfservice-ui-node:
image: oryd/kratos-selfservice-ui-node:v0.8.0-alpha.3
environment:
- KRATOS_PUBLIC_URL=http://kratos:4433/
- KRATOS_BROWSER_URL=http://127.0.0.1:4433/
networks:
- intranet
ports:
- "4455:3000"
restart: on-failure
mailslurper:
image: oryd/mailslurper:latest-smtps
ports:
- '4436:4436'
- '4437:4437'
networks:
- intranet
postgres-keto:
image: postgres:9.6
ports:
- "15432:5432"
environment:
- POSTGRES_USER=keto
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=keto
networks:
- intranet
keto-migrate:
image: oryd/keto:v0.7.0-alpha.1
volumes:
- type: bind
source: ./keto
target: /home/ory
environment:
- LOG_LEVEL=debug
- DSN=postgres://keto:[email protected]:5432/keto?sslmode=disable&max_conns=20&max_idle_conns=4
command: ["migrate", "up", "-y"]
restart: on-failure
depends_on:
- postgres-kratos
networks:
- intranet
keto-perms:
image: oryd/keto:v0.7.0-alpha.1
volumes:
- type: bind
source: ./keto
target: /home/ory
environment:
- KETO_WRITE_REMOTE=keto:4467
- KETO_READ_REMOTE=keto:4466
- LOG_LEVEL=debug
- DSN=postgres://keto:[email protected]:5432/keto?sslmode=disable&max_conns=20&max_idle_conns=4
depends_on:
- postgres-kratos
networks:
- intranet
keto:
image: oryd/keto:v0.7.0-alpha.1
volumes:
- type: bind
source: ./keto
target: /home/ory
ports:
- '4466:4466'
- '4467:4467'
depends_on:
- keto-migrate
environment:
- DSN=postgres://keto:[email protected]:5432/keto?sslmode=disable&max_conns=20&max_idle_conns=4
networks:
- intranet
command: serve
volumes:
node-modules:
kratos-sqlite:
networks:
intranet:
使用策略
Keto 已配置命名空间app
以在 Flask 应用程序中使用。按照指南检查用户是否有权访问某事我决定为演示项目实施简单的权限策略:
-
使用 keto-cli 管理权限。
-
为个主题使用电子邮件没有
@
符号。
优点
-
易于使用和维护。
-
可以使用 CI/CD 管道轻松实现自动化。
缺点
-
缺乏 UI 可能会破坏非工程人员的交易
-
此权限政策可能会因个人数据使用而违反GDPR、HIPAA或任何其他合规性。
烧瓶部分
HTTP_STATUS_FORBIDDEN = 403
@blueprint.route("/", methods=["GET", "POST"])
def home():
"""Home page."""
if 'ory_kratos_session' not in request.cookies:
return redirect(settings.KRATOS_UI_URL)
response = requests.get(
f"{settings.KRATOS_EXTERNAL_API_URL}/sessions/whoami",
cookies=request.cookies
)
active = response.json().get('active')
if not active:
abort(HTTP_STATUS_FORBIDDEN)
email = response.json().get('identity', {}).get('traits', {}).get('email').replace('@', '')
# Check permissions
response = requests.get(
f"{settings.KETO_API_READ_URL}/check",
params={
"namespace": "app",
"object": "homepage",
"relation": "read",
"subject_id": email,
}
)
if not response.json().get("allowed"):
abort(HTTP_STATUS_FORBIDDEN)
return render_template("public/home.html")
@blueprint.route("/oathkeeper", methods=["GET", "POST"])
def oathkeeper():
""" An example route to demo oathkeeper integration with Kratos """
return {"message": "greetings"}
请注意
-
考虑使用Kratos SDK和Keto SDK的
authorization
和authentication
软件包。使用 SDK,您的代码将更具可读性,而不仅仅是调用一些神奇的端点。 -
请注意配置登录会话和cookie。
-
最好使用Ory Cloud,而不是仅仅因为 Ory 管理 Ory Kratos 而让您的团队管理它,并且您不需要为您的服务启用可观察性/日志记录/指标。
更多推荐
所有评论(0)