簡體   English   中英

使用 Express 和 express-basic-auth package 的基本身份驗證。 使用 javaScript 觸發登錄和注銷

[英]Basic Authentication using Express and express-basic-auth package. Trigger login and logout with javaScript

要注銷使用基本身份驗證登錄的用戶,我正在嘗試遵循以下建議: link1 link2

我正在使用express-basic-auth來保護我的應用程序中的一些路由。 使用它的受保護路由的示例如下:

const basicAuth = require('express-basic-auth');
const protect = basicAuth({
  users: { 'admin': 'secret' },
  challenge: true
})
app.get('/protected', protect, function(req, res) {
  console.log("authorization header ", req.headers.authorization);
  console.log("user ", req.auth);
  res.send('Success!');
});

basicAuth中使用challenge: true我們會彈出一個輸入用戶名和密碼的窗口。 如果輸入的信息正確,我們就會Success! 寫在屏幕上。

當我想注銷用戶時出現問題。 我研究並發現基本身份驗證不是圍繞注銷建立的,但有一些黑客方法可以做到這一點。

要注銷,我們基本上需要使用錯誤的憑據登錄。 我們不能要求用戶這樣做,所以我想編寫一個 JavaScript 片段,該片段會使用錯誤的憑據登錄並將該代碼鏈接到注銷按鈕。

要注銷,我創建了一個注銷按鈕,並使用帶有GET方法和錯誤憑據的fetch強制注銷。 代碼如下:

const logoutLink = document.getElementById("logout");
logout.addEventListener("click", handleLogoutClick)
function handleLogoutClick() {
// Wrong credentials
let username = 'admin';
let password = 'passwd';
let url = `http://localhost:3000/protected`; // url cannot have credentials

let headers = new Headers();


headers.append('Content-Type', 'text/json');
headers.set('Authorization', 'Basic ' + btoa(username + ":" + password));

fetch(url, {method:'GET',
        headers: headers})
.then(response => {
  if (!response.ok) throw new Error(response.status);
  return response.json();})
.then(data => {console.log("Data is", data)})
.catch(err => {console.log("Error is", err)})

上面的代碼片段在 Chrome 上注銷用戶時有效,但在 Firefox 中無效。

在我的瀏覽器中,如果我想注銷用戶並且我這樣做: http://user:wrongPassword@localhost:3000/protected ,那么它會注銷用戶(適用於 Chrome 和 Firefox)

However, I can't make a fetch request to http://user:wrongPassword@localhost:3000/protected URL so I have to make a request to http://localhost:3000/protected and passed the credentials as a header.

另外為了測試注銷請求可能有什么問題,我嘗試使用 javascript 發出登錄請求。 當我在瀏覽器中看到console.log語句以及我在運行應用程序的終端上看到的語句時,它似乎有效(獲得狀態200 )。 但是當我嘗試訪問受保護的路由時,我會彈出basicAuth彈出窗口以再次輸入憑據。 (如果我在瀏覽器中手動登錄,它不會再次要求登錄憑據)

登錄代碼(這似乎在我返回的 200 狀態請求方面有效)但實際上並不有效,如下所示:

function userForm() {
    const loginForm = document.getElementById('login-form');
    loginForm.addEventListener("submit", handleFormSubmit)
    function handleFormSubmit(e) {
      e.preventDefault();
      
      const formData = new FormData(document.querySelector('form'));
      const formObject = {}
      for (let pair of formData.entries()) {
        formObject[pair[0]] = pair[1];
      }
      console.log(formObject);
      const {username, password} = formObject;
      const url = `http://localhost:3000/protected`;
      let headers = new Headers();
      headers.append('Content-Type', 'text/json');
      headers.set('Authorization', 'Basic ' + btoa(username + ":" + password));

      (async () => {
          try {
            const response = await fetch(url, {
            method: 'GET',
            headers: headers
            });

            console.log("response is", response);
            if (response.status === 200) {
              window.location.href = url;
            }
          } catch (error) {
            console.log("An error occured in form submission");
          }
          
        })(url, headers);
    }
  }
  userForm();

我們得到一個200response.status但是當瀏覽器被重定向到受保護的路由時,我會彈出一個輸入憑據。 當我使用 vanilla JS 對受保護的路由進行fetch調用時,我可以看到打印到終端的授權標頭和用戶值(來自console.log app.get('/protected', protect, function(req, res) {}

我知道basicAuth不是在生產中使用的東西。 但我想知道為什么這樣的登錄不起作用。 還有為什么注銷不適用於 firefox 但適用於 chrome。 還有一些我可以參考的資源可能會為我清除basicAuth package exxpress-basic-auth在這方面不是很清楚。

關閉瀏覽器或刷新瀏覽器會注銷用戶。 但是,如果我可以為注銷按鈕編寫腳本,也許還可以為登錄編寫腳本,那就更好了。

在搜索和試驗之后,我發現了如何使用 javascript 注銷使用基本身份驗證登錄的用戶,以及為什么我上面使用的方法似乎有效但實際上並沒有奏效。

Javascript 代碼用於注銷有效的用戶(在 chrome 和 firefox 中檢查)。

const logoutLink = document.getElementById("logout");
logout.addEventListener("click", handleLogoutClick)
function handleLogoutClick() {
  // url for protected route
  const url = 'http://localhost:3000/users'
  // wrong credentials to remove
  // to trigger a login with wrong credentials
  const username = 'fakeUser';
  const password = 'randomPassword';
  var http = new XMLHttpRequest();
  // xhr request with wrong credentials 
  // so as to flush out the saved correct credentials
  http.open("get", url, false, username, password);
  http.send("");
  // status 401 is for accessing unauthorized route
  // will get this only if attempt to flush out correct credentials was successful
  if (http.status === 401) {
    alert("You're logged out now");
    window.location.href = "/";
  } else {
    alert("Logout failed");
  }
}

上述方法之所以有效,是因為它建立了一個瀏覽器 session。

Javascript 注銷我們使用headers.set('Authorization', 'Basic ' + btoa(username + ":" + password)); 不起作用,因為該方法僅適用於該特定請求。

這就是為什么在headers中使用帶有錯誤憑據的方法會引發401 (未經授權的請求),但僅針對該特定請求。 由於它僅針對該特定請求發送錯誤的用戶憑據,因此無法清除正確的用戶憑據並注銷用戶。

只是想添加到 AJ 的答案,因為它對我有用。 我想阻止后退按鈕訪問頁面,所以我在我的快速后端添加了這些標題,這阻止了緩存版本的加載:

res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
res.header('Expires', '-1');
res.header('Pragma', 'no-cache');

這是取自這個答案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM