Nginx Ingress 带基本身份验证会破坏预检请求

4

我正在为我的后端服务设置基本认证的简单规则。当我用curl或postman发送请求时,它完美地运行。但是当我的前端应用程序尝试执行相同的操作时,就会出现问题。据我所知,浏览器会发送预检请求(OPTIONS方法),用于CORS策略检查。问题在于此请求未添加Authorization标头,服务器响应401错误。有没有办法让Ingress忽略特定方法的授权?

这里是我的Ingress(nginx)配置:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: somesome-routing
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
spec:
  rules:
    - host: somesome.com
      http:
        paths:
          - path: /
            backend:
              serviceName: backend-service
              servicePort: 80

1
你找到解决方案了吗?我遇到了相同的问题,即Ingress尝试验证OPTIONS但不包括身份验证请求标头,因此失败。我在文档中找不到任何解决方法。 - ikbenben
2个回答

1

Auth或外部认证会破坏预检/跨域资源共享,因为默认模板无法正确处理OPTIONS请求。实际上,所有HTTP方法的身份验证处理方式都是相同的。

因此,需要回答的问题是“如何以不同的方式处理OPTIONS请求?”或“如何仅将身份验证应用于特定的方法”。 您可以通过配置片段来实现此目的。(请参阅:nginx-ingress文档

您可以在这里找到类似的问题:如何在ngnix ingress中对特定的HTTP方法进行基本身份验证?


请不要在多个问题上发布相同的答案。相反,将答案调整到所问的问题。如果这些问题完全相同,请投票/标记关闭。 - Jean-François Fabre

0

我最终采用了两个入口的解决方法 - 一个安全的入口将流量路由到前端应用程序,另一个不安全的入口将流量路由到基于nginx的API网关,该网关本身定义了身份验证规则:

#secure-ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: secure-routing
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-staging"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
spec:
  rules:
    - host: somesome.com
      http:
        paths:
          - path: /
            backend:
              serviceName: frontend-service
              servicePort: 80


#ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: routing
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-staging"
spec:
  rules:
    - host: api.somesome.com
      http:
        paths:
          - path: /
            backend:
              serviceName: api-gateway-service
              servicePort: 80

# api-gateway/nginx.conf
worker_processes      1;

events {
    worker_connections  1024;
}

http {
    log_format timed_combined '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time';
    access_log           /var/log/nginx/access.log timed_combined;
    client_max_body_size 20M;
    default_type         application/octet-stream;
    include              mime.types;
    keepalive_timeout    65;
    resolver             ${RESOLVER} ipv6=off;
    sendfile             on;

    server {
        listen          80;
        server_name     localhost;
        gzip            on;
        gzip_comp_level 6;
        gzip_min_length 1000;
        gzip_types      text/plain application/json application/xml;

        location ~* ^/backend_path {
            add_header 'Access-Control-Allow-Headers' 'authorization,content-type,iplanetdirectorypro';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, OPTIONS, DELETE';

            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_send_timeout 6000;
            proxy_read_timeout 6000;

            proxy_pass http://${BACKEND}$request_uri;
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接