是否有可能注销用户从一个网站,如果他是使用基本身份验证?

杀死会话是不够的,因为一旦用户通过身份验证,每个请求都包含登录信息,因此用户下次使用相同的凭据访问站点时将自动登录。

目前唯一的解决方案是关闭浏览器,但从可用性的角度来看,这是不可接受的。


当前回答

其实很简单。

只需在浏览器中访问以下内容,并使用错误的凭据: http://username:password@yourdomain.com

这应该会“让你退出”。

其他回答

其实很简单。

只需在浏览器中访问以下内容,并使用错误的凭据: http://username:password@yourdomain.com

这应该会“让你退出”。

这适用于IE/Netscape/Chrome浏览器:

      function ClearAuthentication(LogOffPage) 
  {
     var IsInternetExplorer = false;    

     try
     {
         var agt=navigator.userAgent.toLowerCase();
         if (agt.indexOf("msie") != -1) { IsInternetExplorer = true; }
     }
     catch(e)
     {
         IsInternetExplorer = false;    
     };

     if (IsInternetExplorer) 
     {
        // Logoff Internet Explorer
        document.execCommand("ClearAuthenticationCache");
        window.location = LogOffPage;
     }
     else 
     {
        // Logoff every other browsers
    $.ajax({
         username: 'unknown',
         password: 'WrongPassword',
             url: './cgi-bin/PrimoCgi',
         type: 'GET',
         beforeSend: function(xhr)
                 {
            xhr.setRequestHeader("Authorization", "Basic AAAAAAAAAAAAAAAAAAA=");
         },

                 error: function(err)
                 {
                    window.location = LogOffPage;
             }
    });
     }
  }


  $(document).ready(function () 
  {
      $('#Btn1').click(function () 
      {
         // Call Clear Authentication 
         ClearAuthentication("force_logout.html"); 
      });
  });          

正如其他人所说,我们需要获得相同的URL并发送一个错误(例如401:StatusUnauthorized之类的),仅此而已。

我使用Get方法让它知道我需要登出,

下面是一个使用golang进行写作的完整示例。

package main

import (
    "crypto/subtle"
    "fmt"
    "log"
    "net/http"
)

func BasicAuth(username, password, realm string, handlerFunc http.HandlerFunc) http.HandlerFunc {

    return func(w http.ResponseWriter, r *http.Request) {
        queryMap := r.URL.Query()
        if _, ok := queryMap["logout"]; ok { // localhost:8080/public/?logout
            w.WriteHeader(http.StatusUnauthorized) // 401
            _, _ = w.Write([]byte("Success logout!\n"))
            return
        }

        user, pass, ok := r.BasicAuth()

        if !ok ||
            subtle.ConstantTimeCompare([]byte(user), []byte(username)) != 1 ||
            subtle.ConstantTimeCompare([]byte(pass), []byte(password)) != 1 {
            // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate
            w.Header().Set("WWW-Authenticate", `Basic realm="`+realm+`", charset="UTF-8"`)
            w.WriteHeader(http.StatusUnauthorized)
            _, _ = w.Write([]byte("Unauthorised.\n"))
            return
        }

        handlerFunc(w, r)
    }
}

type UserInfo struct {
    name string
    psw  string
}

func main() {

    portNumber := "8080"
    guest := UserInfo{"guest", "123"}

    // localhost:8080/public/  -> ./public/everyone
    publicHandler := http.StripPrefix(
        "/public/", http.FileServer(http.Dir("./public/everyone")),
    )

    publicHandlerFunc := func(w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodGet:
            publicHandler.ServeHTTP(w, r)
        /*
            case http.MethodPost:
            case http.MethodPut:
            case http.MethodDelete:
        */
        default:
            return
        }
    }

    http.HandleFunc("/public/",
        BasicAuth(guest.name, guest.psw, "Please enter your username and password for this site",
            publicHandlerFunc),
    )

    log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", portNumber), nil))
}

当您已经登出时,您需要刷新(F5)页面。否则,您可能会看到旧内容。

根据我上面读到的内容,我得到了一个适用于任何浏览器的简单解决方案:

1)在你登出页面,你调用ajax到你的登录后端。您的登录后端必须接受注销用户。一旦后端接受,浏览器将清除当前用户并假定为“注销”用户。

$.ajax({
    async: false,
    url: 'http://your_login_backend',
    type: 'GET',
    username: 'logout'
});      

setTimeout(function () {
    window.location.href = 'http://normal_index';
}, 200);

2)现在当用户回到正常的索引文件时,它将尝试自动进入系统,用户“logout”,在第二次你必须通过回复401来调用登录/密码对话框来阻止它。

3)有很多方法可以做到这一点,我创建了两个登录后端,一个接受注销用户和一个不接受。我的正常登录页面使用一个不接受,我的注销页面使用一个接受它。

 function logout(url){
    var str = url.replace("http://", "http://" + new Date().getTime() + "@");
    var xmlhttp;
    if (window.XMLHttpRequest) xmlhttp=new XMLHttpRequest();
    else xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    xmlhttp.onreadystatechange=function()
    {
        if (xmlhttp.readyState==4) location.reload();
    }
    xmlhttp.open("GET",str,true);
    xmlhttp.setRequestHeader("Authorization","Basic xxxxxxxxxx")
    xmlhttp.send();
    return false;
}