在 traefik.frontend.auth.forward.address 服务中提取参数
Extracting params in traefik.frontend.auth.forward.address service
总结
我正在尝试使用 Traefik 的 traefik.frontend.auth.forward.address
设置来设置身份验证直通。我的主要 Web 服务在容器上有 traefik.frontend.auth.forward.address=login.mydomain.com
标签。 Traefik 似乎正确地将针对 mydomain.com
的传入请求转发到 login.mydomain.com
,但是当提交登录表单时,POST 请求在到达登录服务之前会变成 GET 请求,并且原始 POST 请求的参数似乎丢失了。用户永远无法登录。
容器
docker run -d \
-l "traefik.frontend.rule=Host:login.mydomain.com; Method:GET, POST" \
-l "traefik.enable=true" \
login-service
docker run -d \
-l "traefik.frontend.rule=Host:mydomain.com" \
-l "traefik.frontend.auth.forward.address=https://login.mydomain.com" \
-l "traefik.frontend.auth.forward.authResponseHeaders=cookie" \
-l "traefik.enable=true" \
web-service
问题
使用 auth.forward.address
,我应该在我的登录服务中看到来自原始 POST 请求的参数吗?由于 Traefik 将其转换为 GET 请求,我应该在该请求的哪个位置查找参数?或者,也许我配置错误?可能缺少 authResponseHeaders
标志?
什么有效
请求 mydomain.com
显示来自 login-service
的登录表单,URL 继续显示 mydomain.com
;重定向到 login.mydomain.com
是在幕后发生的,这是正确的。
登录服务我也自己测试过,好像可以。它承载一个向服务提交 POST 请求的表单,然后以 200 OK 和 Set-Cookie
header 响应。事实上,当我直接进入 login.mydomain.com
时,我可以登录,这会设置我的 cookie,我可以进入 mydomain.com
并跳过登录屏幕。
什么不起作用
提交登录表单时,POST 请求作为 GET 请求和 POST 请求中的数据命中 login-service
(由该服务中的日志证明)似乎不见了。 Traefik 添加了一个 x-forwarded-method
设置为 POST
,但我找不到原始 POST 请求中的数据。我需要我的登录表单中的参数来验证它们,但它们似乎没有通过登录服务。
Traefik 配置
我认为我的 Traefik 配置与这里无关,但为了完整起见,我将其包括在内。
checkNewVersion = true
logLevel = "DEBUG"
defaultEntryPoints = ["https","http"]
sendAnonymousUsage = true
[api]
dashboard = true
debug = true
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[retry]
[docker]
endpoint = "unix:///var/run/docker.sock"
watch = true
exposedbydefault = false
[acme]
email = "admin@mydomain.com"
storage = "acme.json"
entryPoint = "https"
OnHostRule = true
[acme.httpChallenge]
entryPoint = "http"
我找到了 Traefik's auth forward code。果然,请求 body 没有传递到下游的认证服务;只有 header 能做到这一点。默认表单提交行为就这么多了。
为了解决这个问题,我重新设计了我的 client-side 身份验证逻辑,以提交一个 POST 请求,其中包含 在 header 中的凭据的 body,使用 XMLHttpRequest.setRequestHeader
.
设置
要让它发挥作用,还需要一个条件。我需要使用来自身份验证服务器的 Set-Cookie
header return 设置 cookies client-side,但是如果服务器 return 是 200 OK
登录成功,Traefik 将立即将原始请求传递到用户的预期目的地——这意味着 Set-Cookie
header 永远不会到达用户。当身份验证成功时,我所做的就是 return a 418 I'm a teapot
来解决这个问题。这允许 Set-Cookie
header 返回到用户的浏览器,以便可以设置用户的身份验证令牌。然后客户端自动重新加载预期的页面,这次使用正确的 cookie 集,现在身份验证服务器 return 如果它看到所请求服务的有效 cookie,则 200 OK
。
客户端代码如下所示:
<form id="form" method="post" action="/">
Username: <input type="text" name="username" />
Password: <input type="password" name="password" />
<input type="submit" value="Submit" />
</form>
<script>
// Override the default form submit behavior.
// Traefik doesn't pass along body as part of proxying to the auth server,
// so the credentials have to be put in the headers instead.
const form = document.getElementById("form");
form.addEventListener('submit', function(event) {
const data = new FormData(form);
var request = new XMLHttpRequest();
request.open("POST", "/", true);
request.setRequestHeader("Auth-Form", new URLSearchParams(data).toString());
request.withCredentials = true;
request.onload = function(e) {
if (request.status == 418) {
window.location = window.location.href;
} else {
alert("Login failed.");
}
};
request.send(data);
event.preventDefault();
}, false);
</script>
我将至少在赏金用完之前将此问题悬而未决,因为我无法想象这是执行此操作的预期方式。我希望有人可以权衡 traefik.frontend.auth.forward.address
应该如何使用。或者,如果有人在 Traefik 中使用了另一种身份验证代理策略,我很想知道。
总结
我正在尝试使用 Traefik 的 traefik.frontend.auth.forward.address
设置来设置身份验证直通。我的主要 Web 服务在容器上有 traefik.frontend.auth.forward.address=login.mydomain.com
标签。 Traefik 似乎正确地将针对 mydomain.com
的传入请求转发到 login.mydomain.com
,但是当提交登录表单时,POST 请求在到达登录服务之前会变成 GET 请求,并且原始 POST 请求的参数似乎丢失了。用户永远无法登录。
容器
docker run -d \
-l "traefik.frontend.rule=Host:login.mydomain.com; Method:GET, POST" \
-l "traefik.enable=true" \
login-service
docker run -d \
-l "traefik.frontend.rule=Host:mydomain.com" \
-l "traefik.frontend.auth.forward.address=https://login.mydomain.com" \
-l "traefik.frontend.auth.forward.authResponseHeaders=cookie" \
-l "traefik.enable=true" \
web-service
问题
使用 auth.forward.address
,我应该在我的登录服务中看到来自原始 POST 请求的参数吗?由于 Traefik 将其转换为 GET 请求,我应该在该请求的哪个位置查找参数?或者,也许我配置错误?可能缺少 authResponseHeaders
标志?
什么有效
请求 mydomain.com
显示来自 login-service
的登录表单,URL 继续显示 mydomain.com
;重定向到 login.mydomain.com
是在幕后发生的,这是正确的。
登录服务我也自己测试过,好像可以。它承载一个向服务提交 POST 请求的表单,然后以 200 OK 和 Set-Cookie
header 响应。事实上,当我直接进入 login.mydomain.com
时,我可以登录,这会设置我的 cookie,我可以进入 mydomain.com
并跳过登录屏幕。
什么不起作用
提交登录表单时,POST 请求作为 GET 请求和 POST 请求中的数据命中 login-service
(由该服务中的日志证明)似乎不见了。 Traefik 添加了一个 x-forwarded-method
设置为 POST
,但我找不到原始 POST 请求中的数据。我需要我的登录表单中的参数来验证它们,但它们似乎没有通过登录服务。
Traefik 配置
我认为我的 Traefik 配置与这里无关,但为了完整起见,我将其包括在内。
checkNewVersion = true
logLevel = "DEBUG"
defaultEntryPoints = ["https","http"]
sendAnonymousUsage = true
[api]
dashboard = true
debug = true
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[retry]
[docker]
endpoint = "unix:///var/run/docker.sock"
watch = true
exposedbydefault = false
[acme]
email = "admin@mydomain.com"
storage = "acme.json"
entryPoint = "https"
OnHostRule = true
[acme.httpChallenge]
entryPoint = "http"
我找到了 Traefik's auth forward code。果然,请求 body 没有传递到下游的认证服务;只有 header 能做到这一点。默认表单提交行为就这么多了。
为了解决这个问题,我重新设计了我的 client-side 身份验证逻辑,以提交一个 POST 请求,其中包含 在 header 中的凭据的 body,使用 XMLHttpRequest.setRequestHeader
.
要让它发挥作用,还需要一个条件。我需要使用来自身份验证服务器的 Set-Cookie
header return 设置 cookies client-side,但是如果服务器 return 是 200 OK
登录成功,Traefik 将立即将原始请求传递到用户的预期目的地——这意味着 Set-Cookie
header 永远不会到达用户。当身份验证成功时,我所做的就是 return a 418 I'm a teapot
来解决这个问题。这允许 Set-Cookie
header 返回到用户的浏览器,以便可以设置用户的身份验证令牌。然后客户端自动重新加载预期的页面,这次使用正确的 cookie 集,现在身份验证服务器 return 如果它看到所请求服务的有效 cookie,则 200 OK
。
客户端代码如下所示:
<form id="form" method="post" action="/">
Username: <input type="text" name="username" />
Password: <input type="password" name="password" />
<input type="submit" value="Submit" />
</form>
<script>
// Override the default form submit behavior.
// Traefik doesn't pass along body as part of proxying to the auth server,
// so the credentials have to be put in the headers instead.
const form = document.getElementById("form");
form.addEventListener('submit', function(event) {
const data = new FormData(form);
var request = new XMLHttpRequest();
request.open("POST", "/", true);
request.setRequestHeader("Auth-Form", new URLSearchParams(data).toString());
request.withCredentials = true;
request.onload = function(e) {
if (request.status == 418) {
window.location = window.location.href;
} else {
alert("Login failed.");
}
};
request.send(data);
event.preventDefault();
}, false);
</script>
我将至少在赏金用完之前将此问题悬而未决,因为我无法想象这是执行此操作的预期方式。我希望有人可以权衡 traefik.frontend.auth.forward.address
应该如何使用。或者,如果有人在 Traefik 中使用了另一种身份验证代理策略,我很想知道。