You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Kotlin CLI安全连接Heroku PostgreSQL并读取JSON数据

安全实现Kotlin CLI连接Heroku PostgreSQL的方案

核心原则:绝对避免直接暴露数据库凭证给CLI

直接把数据库连接字符串硬编码到CLI里,或者分发给用户,等于把数据库完全暴露给任何人——这是绝对不能碰的风险操作。最优方案是通过Django作为中间层代理请求,而非让CLI直接连数据库。


方案一:用Django API作为数据代理(推荐)

让CLI通过调用Django提供的API接口获取数据,由Django负责安全连接数据库并返回JSON,这是最安全的架构。

步骤1:在Django中实现安全的API接口

  1. 创建一个仅返回所需JSON数据的视图,加入API密钥验证(或用户登录态验证,比如JWT)
  2. 把API密钥存在Heroku环境变量中,不要硬编码到代码里

示例Django视图(简化版):

from django.http import JsonResponse
from django.views.decorators.http import require_GET
from django.views.decorators.csrf import csrf_exempt
import os
from .models import TargetModel  # 替换成你的数据模型

@csrf_exempt
@require_GET
def fetch_json_data(request):
    # 验证请求携带的API密钥
    request_api_key = request.GET.get('api_key')
    valid_api_key = os.environ.get('CLI_API_KEY')  # 从Heroku环境变量读取
    
    if request_api_key != valid_api_key:
        return JsonResponse({'error': '无权访问'}, status=401)
    
    # 查询数据库并转换为JSON格式
    queryset = TargetModel.objects.values('field1', 'field2')  # 只返回需要的字段
    return JsonResponse(list(queryset), safe=False)

步骤2:在Kotlin CLI中调用Django API

用HTTP客户端(比如OkHttp、Ktor)发送HTTPS请求,携带合法的API密钥。不要把API密钥硬编码在CLI里,让用户通过参数或配置文件输入(比如./your-cli --api-key=xxx)。

示例Kotlin代码(使用OkHttp):

import okhttp3.OkHttpClient
import okhttp3.Request

fun fetchData(apiKey: String) {
    val client = OkHttpClient()
    val request = Request.Builder()
        .url("https://your-heroku-app.herokuapp.com/fetch-json-data/?api_key=$apiKey")
        .build()

    client.newCall(request).execute().use { response ->
        when {
            !response.isSuccessful -> throw RuntimeException("请求失败,状态码: ${response.code}")
            response.body == null -> throw RuntimeException("无返回数据")
            else -> {
                val jsonData = response.body.string()
                // 处理获取到的JSON数据
                println(jsonData)
            }
        }
    }
}

安全优化

  • 给每个用户生成专属API密钥:在Django中实现用户系统,用户登录后可生成/重置自己的API密钥,便于权限管控和 revoke
  • 启用API请求频率限制:用Django的django-ratelimit等工具防止恶意请求

方案二:直接连接数据库(不推荐,仅作备选)

如果必须让CLI直接连PostgreSQL,一定要做严格的权限限制:

步骤1:创建只读数据库用户

在Heroku PostgreSQL中创建仅拥有SELECT权限的用户,避免全权限凭证泄露:

  1. 进入Heroku数据库终端:heroku pg:psql
  2. 执行SQL命令:
-- 创建只读用户
CREATE USER cli_readonly WITH PASSWORD '强随机密码';
-- 授予所有表的只读权限
GRANT SELECT ON ALL TABLES IN SCHEMA public TO cli_readonly;
-- 设置默认权限,确保新表也能被读取
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO cli_readonly;

步骤2:生成专属连接字符串

在Heroku中为这个只读用户生成独立的连接字符串:

heroku pg:credentials:create cli_readonly

把生成的连接字符串分发给用户(或让用户自行获取),不要硬编码到CLI中。

步骤3:Kotlin CLI中用JDBC连接

使用PostgreSQL JDBC驱动连接数据库,读取数据并转换为JSON:

import java.sql.DriverManager
import org.postgresql.Driver
import com.google.gson.GsonBuilder

fun connectAndFetchData(dbUrl: String) {
    // 注册PostgreSQL驱动
    DriverManager.registerDriver(Driver())
    
    DriverManager.getConnection(dbUrl).use { connection ->
        val statement = connection.createStatement()
        val resultSet = statement.executeQuery("SELECT field1, field2 FROM target_table")
        
        // 把ResultSet转换为JSON
        val gson = GsonBuilder().create()
        val dataList = mutableListOf<MutableMap<String, Any?>>()
        
        while (resultSet.next()) {
            val row = mutableMapOf<String, Any?>()
            row["field1"] = resultSet.getObject("field1")
            row["field2"] = resultSet.getObject("field2")
            dataList.add(row)
        }
        
        println(gson.toJson(dataList))
    }
}

CLI分发的安全注意事项

  • 绝对不要在CLI安装包或代码中嵌入任何敏感信息(API密钥、数据库凭证)
  • 引导用户从你的Django网站获取合法访问凭证(比如登录后生成API密钥)
  • 强制CLI使用HTTPS请求Django API,禁止HTTP传输,避免数据被窃听

内容的提问来源于stack exchange,提问作者8SIXSector

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 04:43:16