Astro 中的 API 密钥和环境变量:完整安全指南

来源:undefined 2025-02-12 15:05:52 1021

当我们使用 astro 开发 web 应用程序时,我们经常需要与外部 api 和服务进行交互。安全地管理凭据和 api 密钥对于保护我们的应用程序至关重要。在本指南中,我们将探索在 astro 项目中管理 api 密钥和环境变量的最佳实践。

astro 中的环境变量

基本配置

在 astro 中,环境变量的处理方式与其他现代框架类似。首先,我们在项目的根目录中创建一个 .env 文件:

1

2

3

4

# .env

public_api_url=https://api.ejemplo.com

private_api_key=tu_clave_secreta

database_url=postgresql://usuario:password@localhost:5432/db

登录后复制

对于 typescript

,建议创建一个 env.d.ts 文件来输入我们的变量:

1

2

3

4

5

6

7

8

9

10

/// <reference types="astro/client" />

interface importmetaenv {

readonly database_url: string;

readonly private_api_key: string;

readonly public_api_url: string;

}

interface importmeta {

readonly env: importmetaenv;

}

登录后复制

访问变量

在 astro 中,我们可以根据上下文以不同的方式访问环境变量:

1

2

3

4

5

---

// en archivos .astro

const apikey = import.meta.env.private_api_key;

const publicurl = import.meta.env.public_api_url;

---

登录后复制

1

2

// en archivos .ts o .js

const apikey = import.meta.env.private_api_key;

登录后复制

前端安全

公共变量与私有变量

astro 遵循环境变量的重要约定:

public_*:可在客户端和服务器上访问 无 public_ 前缀:只能在服务器上访问

1

2

3

# .env

public_api_url=https://api.publica.com    # ✅ visible en el cliente

private_api_key=secreto123                # ⛔ solo servidor

登录后复制

保护敏感密钥

要处理需要身份验证的 api,我们必须创建无服务器端点:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

// src/pages/api/data.ts

export async function get() {

try {

const response = await fetch(https://api.externa.com/data, {

headers: {

authorization: `bearer ${import.meta.env.private_api_key}`

}

});

const data = await response.json();

return new response(json.stringify(data), {

status: 200,

headers: {

content-type: application/json

}

});

} catch (error) {

return new response(json.stringify({ error: error al obtener datos }), {

status: 500

});

}

}

登录后复制

最佳实践

1.环境变量的验证

在应用程序开始时实现验证功能:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

// src/utils/validateenv.ts

export function validateenv() {

const requiredenvvars = [

database_url,

private_api_key,

public_api_url

];

for (const envvar of requiredenvvars) {

if (!import.meta.env[envvar]) {

throw new error(`la variable de entorno ${envvar} es requerida`);

}

}

}

// src/pages/index.astro

---

import { validateenv } from ../utils/validateenv;

if (import.meta.env.mode === development) {

validateenv();

}

---

登录后复制

2. 多重环境管理

为每个环境创建不同的文件:

1

2

3

4

.env                # variables por defecto

.env.development    # variables de desarrollo

.env.production     # variables de producción

.env.local          # variables locales (ignoradas en git)

登录后复制

3.环境变量模板

提供.env.example文件:

1

2

3

4

# .env.example

public_api_url=https://api.ejemplo.com

private_api_key=tu_clave_aqui

database_url=postgresql://usuario:password@localhost:5432/db

登录后复制

4.git配置

确保在 .gitignore 中包含敏感文件:

1

2

3

4

# .gitignore

.env

.env.local

.env.*.local

登录后复制

与外部服务集成

条纹示例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

// src/pages/api/create-payment.ts

import stripe from stripe;

export async function post({ request }) {

const stripe = new stripe(import.meta.env.stripe_secret_key);

try {

const { amount, currency } = await request.json();

const paymentintent = await stripe.paymentintents.create({

amount,

currency

});

return new response(json.stringify({ clientsecret: paymentintent.client_secret }), {

status: 200

});

} catch (error) {

return new response(json.stringify({ error: error.message }), {

status: 400

});

}

}

登录后复制

firebase 示例

1

2

3

4

5

6

7

8

9

10

11

12

// src/lib/firebase.ts

import { initializeapp } from firebase/app;

import { getfirestore } from firebase/firestore;

const firebaseconfig = {

apikey: import.meta.env.public_firebase_api_key,

authdomain: import.meta.env.public_firebase_auth_domain,

projectid: import.meta.env.public_firebase_project_id,

};

export const app = initializeapp(firebaseconfig);

export const db = getfirestore(app);

登录后复制

部署和 ci/cd

vercel 中的配置

1

2

3

# configurar variables en vercel cli

vercel env add private_api_key

vercel env add database_url

登录后复制

github 操作

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

# .github/workflows/deploy.yml

name: deploy

on:

push:

branches: [main]

jobs:

deploy:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v2

- name: deploy to vercel

env:

vercel_token: ${{ secrets.vercel_token }}

private_api_key: ${{ secrets.private_api_key }}

database_url: ${{ secrets.database_url }}

run: vercel deploy --prod --token=$vercel_token

登录后复制

额外的安全提示

密钥轮换:实现定期轮换 api 密钥的系统

1

2

3

4

5

6

7

8

// src/utils/rotateapikey.ts

async function rotateapikey() {

const currentkey = import.meta.env.private_api_key;

const expirationdays = 30;

// lógica para verificar la edad de la clave

// implementar rotación si es necesario

}

登录后复制
使用情况监控:实施日志记录以检测误用

1

2

3

4

5

// src/middleware/apiLogger.ts

export async function apiLogger(request, apiName) {

console.log(`[${new Date().toISOString()}] API Call: ${apiName}`);

// Implementar logging más detallado según necesidades

}

登录后复制

api 密钥和环境变量的安全处理对于任何现代 web 应用程序都至关重要。通过遵循 astro 的这些最佳实践,我们可以:

确保我们的凭证安全 按环境单独配置 实施稳健的验证 安全地集成外部服务

最新文章