【问题标题】:HAProxy http-request redirect a specific path to another pathHAProxy http-request 将特定路径重定向到另一个路径
【发布时间】:2020-06-04 13:08:10
【问题描述】:

我对 HTTP 协议和一点点 HAProxy 非常熟悉,但我以前从未真正搞砸过 URL 重写和重定向。现在,我有 2 个“简单”的 HTTP 重定向要求,我一直很难弄清楚。

  1. https://appserver.example.com 应重定向到 https://appserver.example.com/myapp/webapp/?auth=saml 以将用户指向 saml 登录页面。
  2. https://appserver.example.com/?auth=standard 应该被重定向到 https://appserver.example.com/myapp/webapp/?auth=standard

要求 1 工作正常:

myuser:~ myuser$ curl -I https://appserver.example.com
HTTP/1.1 301 Moved Permanently
Content-length: 0
Location: https://appserver.example.com/myapp/webapp/?auth=saml
Connection: close

myuser:~ myuser$ 

但我很难理解如何实施 #2。正如我所想的那样,关键是添加一个acl,然后在匹配acl 时添加另一个http-request redirect prefix 行。

acl is_auth_std path /?auth=standard
http-request redirect prefix /myapp/webapp/?auth=standard code 301 if is_auth_std

但显然这还不够。 /?auth=standard 仍然重定向到假定的根 URL:

myuser:~ myuser$ curl -I https://appserver.example.com/?auth=standard
HTTP/1.1 301 Moved Permanently
Content-length: 0
Location: https://appserver.example.com/myapp/webapp/?auth=saml
Connection: close

myuser:~ myuser$

这些是我的haproxy.cfg 文件的相关部分:

frontend myapp443-in
    mode http
    bind *:443 ssl crt /etc/haproxy/ssl/myapp.pem
    default_backend myapp443-out
    option forwardfor

    timeout client          60m
    timeout http-keep-alive 10s
    timeout http-request    5s
    timeout tarpit          60s

    acl is_websocket path_beg /myapp/webapp/
    acl is_websocket hdr(Upgrade) -i WebSocket
    acl is_websocket hdr_beg(Host) -i ws

    acl is_root path /

    capture request  header Host len 64

    http-request redirect scheme https code 301 if !{ ssl_fc }
    http-request redirect code 301 location https://%[hdr(host)]/myapp/webapp/?auth=saml if is_root
    acl is_auth_std path /?auth=standard
    http-request redirect prefix /myapp/webapp/?auth=standard code 301 if is_auth_std

backend myapp443-out
    cookie SRVID insert indirect nocache maxidle 30m maxlife 1h
    option forwardfor
    balance leastconn

    option ssl-hello-chk

    option httpchk GET /myapp/webapp/img/favicon.ico
    http-check expect status 200
    default-server inter 1s downinter 3s rise 15 fall 15
    timeout check 1s

    timeout server          60s
    timeout tunnel        3600s
    timeout queue           30s
    timeout connect          5s

    http-request add-header X-Forwarded-Proto https if { ssl_fc }

    redirect scheme https if !{ ssl_fc }

    http-response add-header Strict-Transport-Security max-age=31536000;\ includeSubdomains
    http-response add-header X-Content-Type-Options nosniff
    http-response add-header X-XSS-Protection 1;\ mode=block
    http-response add-header Referrer-Policy no-referrer
    http-response add-header Feature-Policy accelerometer\ 'none';\ ambient-light-sensor\ 'none';\ autoplay\ 'none';\ camera\ 'none';\ display-capture\ 'none';\ document-domain\ 'none';\ fullscreen\ 'none';\ execution-while-not-rendered\ 'none';\ execution-while-out-of-viewport\ 'none';\ gyroscope\ 'none';\ magnetometer\ 'none';\ microphone\ 'none';\ midi\ 'none';\ payment\ 'none';\ picture-in-picture\ 'none';\ publickey-credentials\ 'none';\ sync-xhr\ 'none';\ usb\ 'none';\ wake-lock\ 'none'

    server appserver-01 appserver-01:8443 weight 5 check ssl verify none cookie s1
    server appserver-02 appserver-02:8443 weight 5 check ssl verify none cookie s1

任何想法我错过了什么?

谢谢。

【问题讨论】:

  • 尝试使用url fetch 方法而不是pathurl 连接路径和查询字符串。

标签: url url-rewriting haproxy


【解决方案1】:

您需要使用url_param 来匹配查询字符串中的参数。

frontend myapp443-in
    mode http
    bind *:443 ssl crt /etc/haproxy/ssl/myapp.pem

    option forwardfor

    timeout client          60m
    timeout http-keep-alive 10s
    timeout http-request    5s
    timeout tarpit          60s

    # if not https => redirect, no need to check acls
    http-request redirect scheme https code 301 if !{ ssl_fc }

    acl is_websocket path_beg /myapp/webapp/
    acl is_websocket hdr(Upgrade) -i WebSocket
    acl is_websocket hdr_beg(Host) -i ws

    acl is_root path /

    acl is_not_auth_std url_param(auth) ! standard
    acl is_not_auth_saml url_param(auth) ! saml

    capture request  header Host len 64

    http-request redirect code 301 location https://%[hdr(host)]/myapp/webapp/?auth=standard if is_not_auth_std is_not_auth_saml

    http-request redirect code 301 location https://%[hdr(host)]/myapp/webapp/?auth=saml if is_root

    default_backend myapp443-out

redirect prefix 附加一个您可能不想要的 /

【讨论】:

  • 谢谢,我确实试过了,但仍然得到相同的 HTTP 响应。
  • 很有趣,因为我已经进行了一些卷发,并且得到了 poper 重定向 curl -v 'http://127.0.0.1:8080/?auth=standard' => location: https://127.0.0.1:8080/myapp/webapp/?auth=standardcurl -v 'http://127.0.0.1:8080/' => location: https://127.0.0.1:8080/myapp/webapp/?auth=saml。也许你需要重新安排conf。我将用整个前端更新答案
  • 感谢您,但浏览器失败并显示ERR_TOO_MANY_REDIRECTS。我猜想这是因为acl is_auth_std url_param(auth) standard 接受auth=standard 而不管路径如何。还有其他方法可以考虑整个路径/?auth=standard吗?谢谢
  • 啊,是的,当 auth=standard 已设置时,您不想重定向。我已经用is_not_* 行更新了答案
  • 我应该在帖子中添加一个规则/问题,因此是赏金,但忘记了! :(无论如何,您的回答足以解决帖子上的问题,非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-12
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
  • 2020-06-28
相关资源
最近更新 更多