PostgREST 教程:实现基于JWT的API认证机制

PostgREST 教程:实现基于JWT的API认证机制

postgrest PostgREST是一个开源的RESTful API服务器,用于将PostgreSQL数据库暴露为RESTful API。 - 功能:RESTful API服务器;PostgreSQL数据库;RESTful API。 - 特点:易于使用;轻量级;支持多种编程语言;高性能。 postgrest 项目地址: https://gitcode.com/gh_mirrors/po/postgrest

前言

PostgREST 是一个将 PostgreSQL 数据库直接转换为 RESTful API 的轻量级工具。在前一个教程中,我们创建了一个只读的API端点来获取待办事项列表。本教程将深入探讨如何为API添加认证功能,使特定用户能够修改数据。

认证机制概述

PostgREST 使用 JSON Web Tokens (JWT) 进行认证。JWT 是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为JSON对象。这种认证方式具有以下特点:

  1. 服务器端使用密钥对令牌进行签名
  2. 客户端无法篡改令牌内容
  3. 令牌可以包含过期时间等元数据
  4. 支持自定义声明(claims)

实现步骤详解

第一步:创建可信用户角色

在PostgreSQL中,我们需要为认证用户创建一个专用角色:

-- 创建不可登录的角色
CREATE ROLE todo_user nologin;

-- 授权给authenticator角色(PostgREST使用的角色)
GRANT todo_user TO authenticator;

-- 授予模式访问权限
GRANT USAGE ON SCHEMA api TO todo_user;

-- 授予表操作权限
GRANT ALL ON api.todos TO todo_user;

这里我们创建了todo_user角色,并授予它对api.todos表的完全控制权限。nologin属性表示这个角色不能直接登录数据库,只能通过PostgREST使用。

第二步:生成JWT密钥

JWT的安全性依赖于密钥的保密性。密钥必须满足:

  • 至少32个字符长度
  • 使用高熵值随机生成
  • 妥善保管,不泄露给客户端

可以使用以下命令生成强密钥:

# 确保处理非UTF-8字节序列
export LC_CTYPE=C

# 生成32字符的字母数字密钥
echo "jwt-secret = \"$(< /dev/urandom tr -dc A-Za-z0-9 | head -c32)\"" >> tutorial.conf

将生成的密钥添加到PostgREST的配置文件中后,需要重启服务使配置生效。

第三步:生成JWT令牌

JWT由三部分组成,用点号(.)分隔:

  1. Header - 包含算法和类型信息
  2. Payload - 包含声明(claims)
  3. Signature - 前两部分的签名

生成令牌的bash脚本示例:

#!/bin/bash
set -e

JWT_SECRET='your_secure_secret_here'

_base64() { openssl base64 -e -A | tr '+/' '-_' | tr -d '='; }

header=$(echo -n '{"alg":"HS256","typ":"JWT"}' | _base64)
payload=$(echo -n "{\"role\":\"todo_user\"}" | _base64)
signature=$(echo -n "$header.$payload" | openssl dgst -sha256 -hmac "$JWT_SECRET" -binary | _base64)

echo -n "$header.$payload.$signature"

重要提示:虽然JWT看起来是加密的,但实际上只是进行了签名。任何人都可以解码并查看payload内容,因此不应在其中存储敏感信息。

第四步:使用令牌进行API操作

获得令牌后,可以通过Authorization头进行认证请求:

# 设置环境变量
export TOKEN="your_generated_token"

# 创建新待办事项
curl http://localhost:3000/todos -X POST \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"task": "学习认证机制"}'

# 批量更新所有待办事项为已完成
curl http://localhost:3000/todos -X PATCH \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"done": true}'

第五步:添加令牌过期时间

为增强安全性,应为JWT设置合理的过期时间。PostgREST支持标准的exp声明,表示令牌的过期时间(Unix时间戳)。

计算5分钟后的Unix时间戳:

exp=$(( $(date +%s) + 300 ))
echo $exp

然后在生成令牌时包含exp声明:

payload=$(echo -n "{\"role\":\"todo_user\",\"exp\":$exp}" | _base64)

过期后,API将返回401 Unauthorized错误。

高级主题:即时令牌撤销

在某些情况下,即使令牌未过期,也需要立即撤销其访问权限。PostgREST支持通过db-pre-request配置项实现这一功能。

  1. 创建验证函数:
CREATE SCHEMA auth;
GRANT USAGE ON SCHEMA auth TO web_anon, todo_user;

CREATE OR REPLACE FUNCTION auth.check_token() RETURNS void
LANGUAGE plpgsql AS $$
BEGIN
  IF current_setting('request.jwt.claims', true)::json->>'email' = 
     'disgruntled@mycompany.com' THEN
    RAISE insufficient_privilege
      USING hint = '访问已被拒绝';
  END IF;
END
$$;
  1. 更新配置文件:
db-pre-request = "auth.check_token"
  1. 重启PostgREST后,特定令牌将被拒绝访问。

最佳实践建议

  1. 生产环境应使用更安全的密钥生成方式
  2. 设置合理的令牌过期时间(通常几分钟到几小时)
  3. 考虑实现令牌刷新机制
  4. 敏感操作应使用更细粒度的权限控制
  5. 定期轮换JWT密钥

通过本教程,您已经掌握了PostgREST的基本认证机制实现方法。这种基于JWT的认证方式既安全又灵活,能够满足大多数API的认证需求。

postgrest PostgREST是一个开源的RESTful API服务器,用于将PostgreSQL数据库暴露为RESTful API。 - 功能:RESTful API服务器;PostgreSQL数据库;RESTful API。 - 特点:易于使用;轻量级;支持多种编程语言;高性能。 postgrest 项目地址: https://gitcode.com/gh_mirrors/po/postgrest

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诸莹子Shelley

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值