如今,工程界在其框架中有许多用于身份验证的产品。它们中的许多具有用于身份验证的内置功能以及许多可用于社交登录的库。我们有 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)使用 Ory Kratos 和 Keto 保护 Flask 应用程序的图表

<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的authorizationauthentication软件包。使用 SDK,您的代码将更具可读性,而不仅仅是调用一些神奇的端点。

  • 请注意配置登录会话和cookie。

  • 最好使用Ory Cloud,而不是仅仅因为 Ory 管理 Ory Kratos 而让您的团队管理它,并且您不需要为您的服务启用可观察性/日志记录/指标。

Logo

学AI,认准AI Studio!GPU算力,限时免费领,邀请好友解锁更多惊喜福利 >>>

更多推荐