加入summary 优化http监听逻辑,实现基本身份认证

This commit is contained in:
dexter
2022-03-01 20:42:25 +08:00
parent 37586d4a0b
commit abe2cdd1fc
11 changed files with 326 additions and 64 deletions

View File

@@ -2,6 +2,8 @@ package util
import (
"context"
"crypto/sha256"
"crypto/subtle"
"encoding/json"
"net"
"net/http"
@@ -69,12 +71,62 @@ func ListenUDP(address string, networkBuffer int) (*net.UDPConn, error) {
return conn, err
}
func CORS(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Credentials", "true")
origin := r.Header["Origin"]
if len(origin) == 0 {
w.Header().Set("Access-Control-Allow-Origin", "*")
} else {
w.Header().Set("Access-Control-Allow-Origin", origin[0])
}
func CORS(next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Credentials", "true")
origin := r.Header["Origin"]
if len(origin) == 0 {
w.Header().Set("Access-Control-Allow-Origin", "*")
} else {
w.Header().Set("Access-Control-Allow-Origin", origin[0])
}
if next != nil {
next.ServeHTTP(w, r)
}
})
}
func BasicAuth(u, p string, next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Extract the username and password from the request
// Authorization header. If no Authentication header is present
// or the header value is invalid, then the 'ok' return value
// will be false.
username, password, ok := r.BasicAuth()
if ok {
// Calculate SHA-256 hashes for the provided and expected
// usernames and passwords.
usernameHash := sha256.Sum256([]byte(username))
passwordHash := sha256.Sum256([]byte(password))
expectedUsernameHash := sha256.Sum256([]byte(u))
expectedPasswordHash := sha256.Sum256([]byte(p))
// 使用 subtle.ConstantTimeCompare() 进行校验
// the provided username and password hashes equal the
// expected username and password hashes. ConstantTimeCompare
// 如果值相等则返回1否则返回0。
// Importantly, we should to do the work to evaluate both the
// username and password before checking the return values to
// 避免泄露信息。
usernameMatch := (subtle.ConstantTimeCompare(usernameHash[:], expectedUsernameHash[:]) == 1)
passwordMatch := (subtle.ConstantTimeCompare(passwordHash[:], expectedPasswordHash[:]) == 1)
// If the username and password are correct, then call
// the next handler in the chain. Make sure to return
// afterwards, so that none of the code below is run.
if usernameMatch && passwordMatch {
if next != nil {
next.ServeHTTP(w, r)
}
return
}
}
// If the Authentication header is not present, is invalid, or the
// username or password is wrong, then set a WWW-Authenticate
// header to inform the client that we expect them to use basic
// authentication and send a 401 Unauthorized response.
w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
http.Error(w, "Unauthorized", http.StatusUnauthorized)
})
}