是否有可能注销用户从一个网站,如果他是使用基本身份验证?
杀死会话是不够的,因为一旦用户通过身份验证,每个请求都包含登录信息,因此用户下次使用相同的凭据访问站点时将自动登录。
目前唯一的解决方案是关闭浏览器,但从可用性的角度来看,这是不可接受的。
是否有可能注销用户从一个网站,如果他是使用基本身份验证?
杀死会话是不够的,因为一旦用户通过身份验证,每个请求都包含登录信息,因此用户下次使用相同的凭据访问站点时将自动登录。
目前唯一的解决方案是关闭浏览器,但从可用性的角度来看,这是不可接受的。
当前回答
以下功能在Firefox 40、Chrome 44、Opera 31和IE 11上均已确认有效。 Bowser用于浏览器检测,也使用jQuery。 —“secUrl”为密码保护区域的url,用户可以从该url退出。 —“redirUrl”为非密码保护区域的url(注销成功页面)。 你可能想增加重定向计时器(目前是200ms)。
function logout(secUrl, redirUrl) { if (bowser.msie) { document.execCommand('ClearAuthenticationCache', 'false'); } else if (bowser.gecko) { $.ajax({ async: false, url: secUrl, type: 'GET', username: 'logout' }); } else if (bowser.webkit) { var xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", secUrl, true); xmlhttp.setRequestHeader("Authorization", "Basic logout"); xmlhttp.send(); } else { alert("Logging out automatically is unsupported for " + bowser.name + "\nYou must close the browser to log out."); } setTimeout(function () { window.location.href = redirUrl; }, 200); }
其他回答
所有你需要的是重定向用户注销URL和返回401未经授权的错误。在错误页面(必须在没有基本身份验证的情况下访问)上,您需要提供到主页的完整链接(包括方案和主机名)。用户将点击此链接,浏览器将再次要求凭据。
Nginx的示例:
location /logout {
return 401;
}
error_page 401 /errors/401.html;
location /errors {
auth_basic off;
ssi on;
ssi_types text/html;
alias /home/user/errors;
}
错误页面/home/user/errors/401.html:
<!DOCTYPE html>
<p>You're not authorised. <a href="<!--# echo var="scheme" -->://<!--# echo var="host" -->/">Login</a>.</p>
让用户点击指向https://log:out@example.com/的链接。这将用无效的凭证覆盖现有的凭证;注销它们。
这是通过在URL中发送新的凭证来实现的。在本例中,user="log" password="out"。
其实很简单。
只需在浏览器中访问以下内容,并使用错误的凭据: http://username:password@yourdomain.com
这应该会“让你退出”。
使用会话ID (cookie) 使服务器上的会话ID失效 不接受会话id无效的用户
正如其他人所说,我们需要获得相同的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)页面。否则,您可能会看到旧内容。