使用无服务器函数保护 API 密钥
想象一下,您需要开发一个 APP 的前端,该 APP 需要从MovieDB API 获取最受欢迎的电影列表。
我们开始做吧 !
前往MovieDB并注册以获取您自己的 API 密钥并继续操作。
我们将使用 create-react-app 创建一个名为protectingapisecrets的新项目,并开始编写前端代码
npx create-react-app protectingapisecrets
cd protectingapisecrets
touch .env
npm install axios
使用您最喜欢的代码编辑器打开此项目,编辑您的.env文件并添加一个带有 API 密钥的变量
// .env
REACT_APP_API_KEY=<<your api key>>
接下来打开你的.gitignore文件并添加一行你的.env文件,最后删除src文件夹中的所有文件并创建一个干净的 i* ndex.js * App.js和App.css
开始编码
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// App.js
import React, { useState, useEffect } from "react"
import axios from "axios"
import "./App.css"
const App = () => {
const [movies, setMovies] = useState(null)
async function fetchMovies() {
const url = `https://api.themoviedb.org/3/movie/popular?api_key=${process.env.REACT_APP_API_KEY}&language=en-US&page=1`
const response = await axios.get(url)
const data = response.data.results
setMovies(data)
}
useEffect(() => {
fetchMovies()
}, [])
return (
<>
{movies === null ? (
<div className="loading">
<h2>Loading ...</h2>
</div>
) : (
<>
<div className="container">
{movies.map((movie) => (
<div className="movie" key={movie.id}>
<img src={`https://image.tmdb.org/t/p/w185/${movie.poster_path}`} alt={movie.title} />
</div>
))}
</div>
</>
)}
</>
)
}
export default App
// App.css
*,
*::after,
*::before {
margin: 0rem;
padding: 0rem;
box-sizing: inherit;
}
html {
font-size: 62.5%;
scroll-behavior: smooth;
}
body {
box-sizing: border-box;
background-color: #222831;
}
.loading {
padding-top: 5rem;
text-align: center;
}
.loading h2 {
color: white;
font-size: 2rem;
}
.container {
margin: auto;
padding: 2rem;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
max-width: 110rem;
grid-gap: 2rem;
}
.movie img {
width: 100%;
}
太棒了,现在我们开始吧
npm start
并检查一切是否符合我们的预期
部署
惊人的!
我们已经完成了前端,现在是时候部署它了。
使用 Netlify,我们只需三个步骤即可轻松完成此操作:
第一步:创建一个新的 GitHub 存储库并推送您的代码。
第二步:在 Netlify 上创建帐户并将您的帐户连接到您的 GitHub。
第三:在你的 Netlify 面板上选择“从 git 创建新站点”并选择你创建的存储库,你还需要选中“显示高级”并添加一个新变量,如下所示:
单击“部署站点”,就这样,我们现在有了应用程序的实时版本!
问题
我们将 API 密钥存储在环境变量中,以防止它在我们的代码中可用,但如果有人在浏览您的网站时打开 chrome dev tools,就可以很快找到您的密钥。
那么,我们可以做些什么来保护我们的 API 密钥?
无服务器函数
我们可以创建一个无服务器函数来为我们处理 API 调用,这样我们就不必公开我们的密钥。
让我们尝试一下,回到你的终端并运行:
npm install netlify-lambda http-proxy-middleware env-cmd
mkdir functions
touch netlify.toml
更新package.json文件中的脚本,使其如下所示:
// package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"lambda-serve": "env-cmd netlify-lambda serve functions",
"lambda-build": "netlify-lambda build functions"
},
将以下行添加到netlify.toml文件并将函数文件夹添加到.gitignorefile
// netlify.toml
[build]
functions = "lambda"
将名为setupProxy.js的文件添加到您的src文件夹并粘贴以下代码:
// setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/.netlify/functions/',
createProxyMiddleware({
target: 'http://localhost:9000',
"pathRewrite": {
"^/\\.netlify/functions": ""
}
})
);
};
此代理设置将允许您根据您所在的环境 ping 不同的端点,如果您处于开发状态,则需要 ping本地主机,而在生产状态,您需要./netlify/functions端点。
编写函数代码
让我们在函数目录中创建一个名为getMovies.js的文件
// getMovies.js
const axios = require("axios")
exports.handler = function(event, context, callback) {
const { API_KEY } = process.env
const url = `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}&language=en-US&page=1`
const send = body => {
callback(null, {
statusCode: 200,
body: JSON.stringify(body)
})
}
const getMovies = async () => {
const response = await axios.get(url)
const data = response.data.results
send(data)
}
getMovies()
}
现在我们需要编辑App.js中的fetchMovies函数以使用 serveless 函数,而不是直接 ping moviedb api:
async function fetchMovies() {
const url = `/.netlify/functions/getMovies`
const response = await axios.get(url)
const data = response.data
setMovies(data)
}
最后编辑.env文件并将变量名称从REACT_APP_API_KEY更改为API_KEY
太好了,让我们测试一下吧!
打开两个终端窗口,在第一个窗口上运行npm start ,在第二个窗口上运行 npm run lambda-serve,然后检查网络选项卡
太棒了,我们正在调用隐藏 api 真实端点的无服务器函数,让我们将其部署到 Netlify,打开你的终端并运行:
git add .
git commit -m "finished version"
git push
当你将提交推送到你的 GitHub 仓库时,Netlify 会触发你网站的新部署。你只需额外完成一步即可完成:打开 Netlify 面板,将你在第一次部署时创建的环境变量名称从REACT_APP_API_KEY更改为API_KEY。
我们已经完成了,很快再见!
您可以在这里查看我的 GitHub 仓库:https://github.com/NunoCPNP/protectapisecrets
我部署的版本在这里:https://protectingapisecrets.netlify.app/
鏂囩珷鏉ユ簮锛�https://dev.to/nunocpnp/protecting-api-keys-with-serverless-functions-2ck7