授权在构建应用程序时非常重要,因为它决定了用户在进行身份验证后可以访问哪些操作和资源。
在本文中,我们将了解如何使用 Permit.io 实现授权。为了演示它,我们将使用 Golang 和 HTMX 构建一个简单的书店应用程序(我是一个超级粉丝)。
要完成本教程,应满足以下先决条件:
所有用户(包括管理员)都可以阅读书籍。管理员还可以添加、删除和更新图书。标准用户仅限于阅读书籍。
本教程将指导您设置具有基本授权的书店应用程序。我们将实施:
授权逻辑:使用 Permit.io 定义角色(管理员和标准用户)来限制或授予对不同资源的访问权限。
数据库:设置 PostgreSQL 数据库来存储图书和用户数据。
处理程序: 通过访问控制检查实现查看、添加、更新和删除图书的路由。
前端:使用HTMX动态加载图书数据。
在设置项目时,我们将从设置permit.io开始。导航到仪表板工作区并创建一个新项目。我会给我的书店起个名字。
这将创建两个环境:开发环境和生产环境。
由于我们在本地工作,因此我们将使用开发环境。单击开发环境中的打开仪表板,然后单击创建策略。系统会要求您首先创建一个新资源。单击创建资源。为其命名并说明操作。对于这个项目,我将命名我的书籍,操作将是创建、更新、删除和查看。
接下来,导航到策略编辑器部分。默认情况下,您应该看到已创建的管理员角色。您只需勾选我们添加的查看操作即可,因为默认情况下无法识别它。你需要另一个角色。这将供仅具有阅读权限的用户使用。
单击“创建”,然后单击“角色”并为其指定用户名。创建后,您应该在策略编辑器中看到它,并在刚刚创建的用户角色中勾选视图,如下所示:
接下来是注册将被permit.io授权的用户。通过侧边栏菜单导航回主菜单,您应该仍然有这样的内容:
点击添加用户,然后添加,然后添加用户。填写与数据库中您的用户相对应的详细信息。
完成后,导航回您的项目。在书店项目的开发环境中,单击 3 点图标。您将看到复制 API 密钥的选项。复制并将其保存在某处,因为您的项目将需要它。
创建一个名为 bookstore 的 PostgreSQL 数据库。您需要设置两个表:
CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(255) NOT NULL, password_hash VARCHAR(255) NOT NULL, role VARCHAR(50) NOT NULL );
继续填充此内容,但让每个用户分别拥有管理员和用户角色,并确保它们与 Permit.io 上添加的用户匹配。
CREATE TABLE books ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, author VARCHAR(255) NOT NULL, published_at DATE, created_at TIMESTAMPTZ DEFAULT now() );
您不需要填充此内容,我们将在代码中进行此操作。
您需要安装以下依赖项:
github.com/permitio/permit-golang: 提供在 Go 应用程序中使用 Permit.io 处理基于角色的访问控制 (RBAC) 和权限管理的工具。
github.com/google/uuid:这提供了生成和使用通用唯一标识符 (UUID) 的函数。
github.com/gorilla/mux: 帮助实现 HTTP 请求路由器和调度程序,用于在 Web 应用程序中处理路由。
github.com/joho/godotenv: 这会从 .env 加载环境变量。文件到应用程序中,从而更轻松地管理配置设置。
github.com/lib/pq:这是 Go 的 Postgres 驱动程序,用于与 PostgreSQL 数据库通信。
golang.org/x/crypto: 实现 Go 标准库中未包含的补充加密算法和库。
要安装这些依赖项,您需要初始化一个新的 Go 模块。这是 Go 中依赖管理的起点。
运行此命令:
CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(255) NOT NULL, password_hash VARCHAR(255) NOT NULL, role VARCHAR(50) NOT NULL );
接下来,运行此命令:
CREATE TABLE books ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, author VARCHAR(255) NOT NULL, published_at DATE, created_at TIMESTAMPTZ DEFAULT now() );
这将安装上面列出的所有依赖项。
要设置 PDP,您需要启动 docker。完成后,打开终端并运行以下命令:
go mod init bookstore
之后,您需要使用以下命令运行容器:
go get github.com/google/uuid \ github.com/gorilla/mux \ github.com/joho/godotenv \ github.com/lib/pq \ github.com/permitio/permit-golang \ golang.org/x/crypto
替换
为了构建应用程序,我们的项目结构如下:
docker pull permitio/pdp-v2:latest
首先,我们将 API 密钥添加到 .env 文件中。创建一个,然后创建您的许可 API 密钥,如下所示:
docker run -it -p 7766:7000 --env PDP_DEBUG=True --env PDP_API_KEY=<YOUR_API_KEY> permitio/pdp-v2:latest
创建一个名为 config 的文件夹。在其中创建一个名为 config.go 的文件。添加以下代码:
Bookstore ├── config │ └── config.go │ ├── handlers │ └── handlers.go │ ├── middleware │ └── middleware.go │ ├── models │ └── models.go │ ├── templates │ ├── add.html │ ├── books.html │ ├── index.html │ ├── layout.html │ ├── login.html │ └── update.html │ ├── main.go └── .env
这只是我们设置连接到 PostgreSQL 数据库的配置。
接下来,创建一个名为 handlers 的文件夹,并在其中创建一个名为 handlers.go 的文件。在其中添加以下代码:
export PERMIT_API_KEY=”your_api_key”
除了导入包之外,我们在这里尝试做的是创建一个保存数据库连接和 Permit.io 的结构。我们还提供了一个初始化函数,用于使用本地 PDP 设置 Permit.io。
在 NewHandlers 之后添加以下内容:
package config import ( "database/sql" "fmt" _ "github.com/lib/pq" ) type Config struct { DB *sql.DB Port string DBConfig PostgresConfig } type PostgresConfig struct { Host string Port string User string Password string DBName string } func NewConfig() *Config { return &Config{ Port: "8080", DBConfig: PostgresConfig{ Host: "localhost", Port: "5432", User: "bookstore_user", Password: "your_password", DBName: "bookstore_db", }, } } func (c *Config) ConnectDB() error { connStr := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", c.DBConfig.Host, c.DBConfig.Port, c.DBConfig.User, c.DBConfig.Password, c.DBConfig.DBName, ) db, err := sql.Open("postgres", connStr) if err != nil { return fmt.Errorf("error opening database: %v", err) } if err := db.Ping(); err != nil { return fmt.Errorf("error connecting to database: %v", err) } c.DB = db return nil }
LoginHandler 执行以下操作:
下一步是添加图书处理程序来访问图书。它还将利用 Permit.io 来验证用户的角色。在 LoginHandler 之后添加以下代码:
package handlers import ( "bookstore/middleware" "bookstore/models" "context" "database/sql" "fmt" "html/template" "net/http" "strings" "time" "github.com/google/uuid" "github.com/permitio/permit-golang/pkg/config" "github.com/permitio/permit-golang/pkg/enforcement" permitModels "github.com/permitio/permit-golang/pkg/models" "github.com/permitio/permit-golang/pkg/permit" ) var tmpl = template.Must(template.ParseGlob("templates/*.html")) func StringPtr(s string) *string { return &s } type Handlers struct { db *sql.DB permitClient *permit.Client } func NewHandlers(db *sql.DB, apiKey string) *Handlers { permitConfig := config.NewConfigBuilder(apiKey). WithPdpUrl("http://localhost:7766"). Build() permitClient := permit.NewPermit(permitConfig) if permitClient == nil { panic("Failed to initialize Permit.io client") } return &Handlers{ db: db, permitClient: permitClient, } }
BookHandler 执行以下操作:
接下来,您需要一个处理程序来添加书籍。它还将通过 Permit.io 验证用户的角色,以确保只有授权用户才能添加图书:
CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(255) NOT NULL, password_hash VARCHAR(255) NOT NULL, role VARCHAR(50) NOT NULL );
AddBookHandler 执行以下操作:
您还需要两个处理程序,一个用于删除,另一个用于更新。在 AddBookHandler 函数之后添加此代码:
CREATE TABLE books ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, author VARCHAR(255) NOT NULL, published_at DATE, created_at TIMESTAMPTZ DEFAULT now() );
DeleteBookHandler 执行以下操作:
在DeleteBookHandler函数之后,添加以下内容:
go mod init bookstore
UpdateHandler 执行以下操作:
在整个代码中,您会注意到授权系统是围绕 Permit.io 基于角色的访问控制框架构建的,该框架提供了复杂的权限管理。
该系统还可以对用户操作进行细粒度控制,并允许不同级别的访问权限来查看、创建、更新和删除资源。应用程序中的每个操作都会经过详细的权限检查,确保用户只能执行其授权的操作。
现在我们已经完成了处理程序。创建一个名为 middleware 的文件夹,并在其中创建一个名为 middleware.go 的文件。添加以下代码:
go get github.com/google/uuid \ github.com/gorilla/mux \ github.com/joho/godotenv \ github.com/lib/pq \ github.com/permitio/permit-golang \ golang.org/x/crypto
此中间件包有助于提供安全的密码哈希和身份验证,以及用于在书店应用程序中管理图书的 CRUD 操作。它使用 bcrypt 对密码进行哈希处理以进行安全存储,并在登录期间验证密码哈希值。它还可以防止敏感数据的暴露。
LoginUser 函数通过将用户的输入与存储的密码哈希进行比较来对用户进行身份验证,并在成功登录时检索完整的用户配置文件,不包括密码哈希以增加安全性。
此外,CRUD 操作允许您在数据库中创建、更新、检索和删除图书记录,并通过访问控制确保只有授权用户才能修改或删除他们创建的条目。该软件包还包括一个 GetUserRole 函数来检索用户角色,促进基于角色的访问控制。
创建另一个名为 models 的文件夹,并在其中创建一个名为 models.go 的文件。并添加以下内容:
CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(255) NOT NULL, password_hash VARCHAR(255) NOT NULL, role VARCHAR(50) NOT NULL );
此包为书店应用程序定义了多个数据模型,包括 User、Book 和 LoginRequest 结构,以及用于处理数据库中可为空的 UUID 的自定义 NullUUID 类型。
快完成了。您需要做的下一件事是为您的项目创建模板。您需要创建用于登录和索引的模板,以添加图书、查看图书、删除图书和更新图书。
创建一个名为 templates 的文件夹。这是您的 html 模板所在的位置。
对于登录,创建一个名为 login.html 的文件,并在其中粘贴以下内容:
CREATE TABLE books ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, author VARCHAR(255) NOT NULL, published_at DATE, created_at TIMESTAMPTZ DEFAULT now() );
这个主包充当书店应用程序的入口点。它设置数据库连接、环境配置和 HTTP 路由来处理用户登录和图书管理。
在主函数中,使用 Gorilla Mux 路由器注册路由。 handlers.NewHandlers 函数使用数据库和 Permit.io API 密钥初始化处理程序。它支持用户身份验证(/登录)和图书管理(/books、/add、/delete、/update)等功能。每个路由都映射到特定的 HTTP 方法,组织不同操作的端点。
最后,服务器在端口 8080 上启动,侦听传入请求并记录发生的任何错误。此设置可确保结构化 API 端点配置和环境变量的安全处理。
现在这就是一切了!让我们启动我们的应用程序来看看。结果。要启动服务器,请运行以下命令:
go mod init bookstore
在浏览器中访问http://localhost:8080/login。
让我们首先测试 standard_user 的权限:
您将看到 standard_user 仅限于查看图书,无法添加、删除或更新图书。
现在让我们使用 admin_user 登录看看会发生什么:
您会看到管理员有权执行任何操作!这就是 Permit 的坚固性和易用性!
您可以查看以下资源以了解更多有关 Permit 授权的信息:
在本教程中,我们构建了一个简单的书店管理应用程序,以使用 Go、HTMX 和 Permit.io 实现基于角色的访问控制。授权是应用程序安全的基本方面,因为它确保用户只能访问他们被允许的内容。
在您的应用程序中实施有效的访问控制模型(如 RBAC 或 ABAC)不仅可以保护您的应用程序,还可以增强其可扩展性和合规性。
以上是如何使用 Go、HTMX 和 Permit.io 在书店管理系统中设置授权的详细内容。更多信息请关注PHP中文网其他相关文章!