我正在尝试使用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
标头响应。实际上,当我直接进入login.mydomain.com
时,我可以登录并设置cookie,然后可以进入mydomain.com
并跳过登录屏幕。
提交登录表单时,POST请求将GET请求打到login-service
(由该服务中的日志证明),并且POST请求中的数据似乎消失了。 Traefik将一个x-forwarded-method
设置为POST
,但是我无法在原始POST请求中找到数据。我需要登录表单中的参数来验证它们,并且它们似乎无法进入登录服务。
我认为与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"
答案 0 :(得分:0)
我找到了Traefik's auth forward code。当然,请求主体不会下游传递到身份验证服务。只有标题能做到这一点。默认表单提交行为就这么多了。
要解决此问题,我重新设计了客户端身份验证逻辑,以使用凭据{em>而不是正文(使用files_dict = {}
with open(data_in) as fi:
for line in fi:
x = line.split(',')[1]
if x not in files_dict:
files_dict[x] = open(x + '.csv', 'w')
files_dict[x].write(line)
for file in files_dict.values():
file.close()
进行设置)在凭据中提交了POST请求。
要使其正常工作,还需要再抓一口。我需要使用从身份验证服务器返回的XMLHttpRequest.setRequestHeader
标头在客户端设置cookie,但是如果登录成功后服务器返回Set-Cookie
,Traefik将立即将原始请求传递给用户的预期目标-意味着200 OK
标头将永远不会传递给用户。解决该问题的方法是,验证成功后返回Set-Cookie
。这允许418 I'm a teapot
标头将其返回到用户的浏览器,以便可以设置用户的auth令牌。然后,客户端会自动重新加载预期的页面,这一次设置了正确的cookie,现在,如果认证服务器看到所请求服务的有效cookie,则会返回Set-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中使用了另一种身份验证代理策略,那么我很想听听。