我正在尝试使用带有基本身份验证的Node / Express / Passport / Javascript创建一个简单的登录表单,但无法使其工作。我想要的是有一个页面,您输入您的凭据并点击“登录”。如果这些凭据是正确的,则应将用户重定向到受基本身份验证保护的页面,而无需再次请求我的凭据。这看起来应该很简单,但我一直遇到问题。
目前,我有一个页面,您可以在其中输入登录凭据(用户名和密码)。点击登录会向/ login端点发出axios POST请求,验证登录凭据。如果凭据正确,则此端点返回状态代码200。如果响应为200 Success,我会将用户重定向到基于身份验证的受保护页面。服务器使用passport express中间件来序列化用户并维护用户会话。但是这个信息似乎在重定向时丢失了,我找不到在重定向上设置基本auth头的方法。因此,我重定向的受保护页面再次要求我提供我的凭据。我试图通过再次发送基本身份验证凭据来修复它:
window.location.replace(http://username:password@website/directory/blahblah)
但是大多数现代浏览器似乎都删除了基本的身份验证凭据,因此无效。
我可以通过将用户名和密码放在网址中来使其工作:
window.location.replace(http://website/directory/blahblah?username=uname&password=password)
但这似乎是解决应该有一个简单解决方案的一种可怕且不安全的方式,因为这种方法意味着用户名和密码最终会出现在我的浏览器历史记录中。有没有更好的方法来实现这样的登录表单?
服务器代码是标准快速服务器,它使用带有会话的passport.authenticate中间件。我觉得奇怪的是,当我的POST请求返回时,req.session.passport.user包含序列化用户,因此代码似乎工作正常,所以我怀疑我的HTML代码存在问题。我目前的HTML登录表单如下:
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<form method="get" action="javascript:loginFn()">
<input name="username" type="text" value="uname" >
<input name="password" type="password" value="pword">
<input type="submit">
</form>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const endpoint = 'login';
const nextEndpoint = 'authorize';
//function redirect(url, method) {
// var form = document.createElement('form');
// form.method = method;
// form.action = url;
// document.body.appendChild(form);
// form.submit();
//};
async function loginFn(){
const username = document.querySelector('form [name=username]');
const password = document.querySelector('form [name=password]');
const uriParts = location.href.split('://');
const http = uriParts[0];
uriParts.splice(0, 1);
var targetUri = `${http}://${username.value}:${password.value}@${uriParts.join('://').replace(endpoint, nextEndpoint)}`;
// If credentials valid, the response code will be 200 Success
const res = await axios
.request({
baseURL: targetUri,
// Username and password used for basic auth
method: 'POST',
auth: {
username: username.value,
password: password.value,
},
params: {
login_only: true,
},
})
.catch((err) => {
// Unable to connect to the server, redirect to the NoConnection page.
if (err.message === 'Network Error') {
throw new Error('Unstable database connection');
}
if(err.request.status === 404){
throw new Error('Invalid callback URL');
}
if (err.request.status === 401) {
// Incorrect login credentials
throw new Error('Invalid login credentials');
}
});
if(res.status === 200){
// How do I NOT put the username and password in the URL redirect
window.location.replace(targetUri + '?username=uname&password=pword');
}
}
</script>
</body>
</html>