保护后端 API 个端点(MERN 应用程序)
Securing the Backend API Endpoints (MERN Application)
我已经使用 MERN 制作了一个全栈 Web 应用程序,并使用 Kubernetes 集群进行了部署。
除一个问题外,应用程序运行良好。也就是说,我(作为用户)能够从浏览器访问 API,例如 www.domain-name/api/orders 这给了我 JSON 响应。
我不想要。我需要这个 hidden/restricted.
我正在使用 NGINX-INGRESS 进行路由:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
rules:
- host: shopify.dev
http:
paths:
- path: /api/users/?(.*)
backend:
serviceName: auth-srv
servicePort: 3000
- path: /api/orders/?(.*)
backend:
serviceName: orders-srv
servicePort: 3000
- path: /?(.*)
backend:
serviceName: client-srv
servicePort: 3000
由于请求 /api 和 /*(前端)都是通过 nginx-ingress 路由的,这是应该如何工作的吗?
解决办法是什么?
您的客户端应用程序,在浏览器中是 运行,应该能够从 API 获取数据,因此很明显是您的应用程序发出请求还是您发出请求(作为用户)从同一个浏览器(或另一个 rest 客户端)发出请求,它将通过(假设遵循相同的身份验证过程)。
完全阻止它是不可能的,也不应该要求它,因为用户仍然可以访问相同的数据,无论是通过应用程序还是直接访问。
但是,如果您想隐藏它,因为您不希望普通用户在期待漂亮的前端应用程序时看到一些奇怪的 json 响应(因为他们随机输入了不正确的 url? 你不会故意将它们导航到你应用程序中的此类端点),你可以在你的应用程序中实现该逻辑。
您可以这样做的方法是在前端应用程序发出的所有请求中包含一些自定义 HTTP header(在 axios/fetch 调用中),然后在您的应用程序上实施过滤逻辑backed 将解析此 header 以查看调用是从前端应用程序还是直接进行的(可能是一个中间件,如果它看到没有此 header 的请求,会将用户重定向到根页面)。我以前用过这个解决方案,效果很好。
但请再次注意,这与安全性无关,因为您的数据已经在您的前端应用程序中可用。此外,它与 kubernetes 本身无关,任何高级用户都可以伪造绕过此解决方案的请求。您的数据应该受到身份验证的保护,而不是某些 html 文档。
例如,如果您正在使用 axios
,您可以为所有这样的请求全局设置自定义 header(在前端)。
axios.defaults.headers.common['fromApp'] = true
并且在您的后端,您可以创建一个中间件
const isFrontendRequest = (req, res, next) => {
const h = req.get('fromApp') // get the header
if (!h) {
// handle the request not originating from your app and return
}
next() // custom header was present if we are here, continue normally
}
然后您可以在每个传入请求前全局应用它。
app.use(isFrontendRequest)
我已经使用 MERN 制作了一个全栈 Web 应用程序,并使用 Kubernetes 集群进行了部署。
除一个问题外,应用程序运行良好。也就是说,我(作为用户)能够从浏览器访问 API,例如 www.domain-name/api/orders 这给了我 JSON 响应。
我不想要。我需要这个 hidden/restricted.
我正在使用 NGINX-INGRESS 进行路由:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
rules:
- host: shopify.dev
http:
paths:
- path: /api/users/?(.*)
backend:
serviceName: auth-srv
servicePort: 3000
- path: /api/orders/?(.*)
backend:
serviceName: orders-srv
servicePort: 3000
- path: /?(.*)
backend:
serviceName: client-srv
servicePort: 3000
由于请求 /api 和 /*(前端)都是通过 nginx-ingress 路由的,这是应该如何工作的吗? 解决办法是什么?
您的客户端应用程序,在浏览器中是 运行,应该能够从 API 获取数据,因此很明显是您的应用程序发出请求还是您发出请求(作为用户)从同一个浏览器(或另一个 rest 客户端)发出请求,它将通过(假设遵循相同的身份验证过程)。
完全阻止它是不可能的,也不应该要求它,因为用户仍然可以访问相同的数据,无论是通过应用程序还是直接访问。
但是,如果您想隐藏它,因为您不希望普通用户在期待漂亮的前端应用程序时看到一些奇怪的 json 响应(因为他们随机输入了不正确的 url? 你不会故意将它们导航到你应用程序中的此类端点),你可以在你的应用程序中实现该逻辑。
您可以这样做的方法是在前端应用程序发出的所有请求中包含一些自定义 HTTP header(在 axios/fetch 调用中),然后在您的应用程序上实施过滤逻辑backed 将解析此 header 以查看调用是从前端应用程序还是直接进行的(可能是一个中间件,如果它看到没有此 header 的请求,会将用户重定向到根页面)。我以前用过这个解决方案,效果很好。
但请再次注意,这与安全性无关,因为您的数据已经在您的前端应用程序中可用。此外,它与 kubernetes 本身无关,任何高级用户都可以伪造绕过此解决方案的请求。您的数据应该受到身份验证的保护,而不是某些 html 文档。
例如,如果您正在使用 axios
,您可以为所有这样的请求全局设置自定义 header(在前端)。
axios.defaults.headers.common['fromApp'] = true
并且在您的后端,您可以创建一个中间件
const isFrontendRequest = (req, res, next) => {
const h = req.get('fromApp') // get the header
if (!h) {
// handle the request not originating from your app and return
}
next() // custom header was present if we are here, continue normally
}
然后您可以在每个传入请求前全局应用它。
app.use(isFrontendRequest)