mirror of
https://github.com/woodchen-ink/proxy-go.git
synced 2025-07-18 16:41:54 +08:00
feat(auth): 增强OAuth认证流程的错误处理和日志记录
- 添加详细的OAuth认证流程错误日志 - 增加对OAuth请求各个阶段的参数和状态验证 - 完善错误处理,提供更具体的错误信息和状态码 - 记录认证过程中的关键步骤和错误信息 - 新增客户端IP和请求来源的日志记录 - 优化OAuth令牌和用户信息的验证逻辑
This commit is contained in:
parent
0ce0f75b58
commit
0d10e89a0b
@ -173,51 +173,108 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
|||||||
|
|
||||||
// 验证 state
|
// 验证 state
|
||||||
if _, ok := h.auth.states.Load(state); !ok {
|
if _, ok := h.auth.states.Load(state); !ok {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> 400 (%s) invalid state from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||||
http.Error(w, "Invalid state", http.StatusBadRequest)
|
http.Error(w, "Invalid state", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.auth.states.Delete(state)
|
h.auth.states.Delete(state)
|
||||||
|
|
||||||
|
// 验证code参数
|
||||||
|
if code == "" {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> 400 (%s) missing code parameter from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||||
|
http.Error(w, "Missing code parameter", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 获取访问令牌
|
// 获取访问令牌
|
||||||
redirectURI := getCallbackURL(r)
|
redirectURI := getCallbackURL(r)
|
||||||
|
clientID := os.Getenv("OAUTH_CLIENT_ID")
|
||||||
|
clientSecret := os.Getenv("OAUTH_CLIENT_SECRET")
|
||||||
|
|
||||||
|
// 验证OAuth配置
|
||||||
|
if clientID == "" || clientSecret == "" {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> 500 (%s) missing OAuth credentials from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||||
|
http.Error(w, "Server configuration error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := http.PostForm("https://connect.czl.net/api/oauth2/token",
|
resp, err := http.PostForm("https://connect.czl.net/api/oauth2/token",
|
||||||
url.Values{
|
url.Values{
|
||||||
"code": {code},
|
"grant_type": {"authorization_code"},
|
||||||
"redirect_uri": {redirectURI},
|
"code": {code},
|
||||||
|
"redirect_uri": {redirectURI},
|
||||||
|
"client_id": {clientID},
|
||||||
|
"client_secret": {clientSecret},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get access token: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||||
http.Error(w, "Failed to get access token", http.StatusInternalServerError)
|
http.Error(w, "Failed to get access token", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 检查响应状态码
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> %d (%s) OAuth server returned error status: %s from %s",
|
||||||
|
r.Method, r.URL.Path, resp.StatusCode, utils.GetClientIP(r), resp.Status, utils.GetRequestSource(r))
|
||||||
|
http.Error(w, "OAuth server error: "+resp.Status, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var token OAuthToken
|
var token OAuthToken
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&token); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&token); err != nil {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to parse token response: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||||
http.Error(w, "Failed to parse token response", http.StatusInternalServerError)
|
http.Error(w, "Failed to parse token response", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验证访问令牌
|
||||||
|
if token.AccessToken == "" {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> 500 (%s) received empty access token from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||||
|
http.Error(w, "Received invalid token", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
req, _ := http.NewRequest("GET", "https://connect.czl.net/api/oauth2/userinfo", nil)
|
req, _ := http.NewRequest("GET", "https://connect.czl.net/api/oauth2/userinfo", nil)
|
||||||
req.Header.Set("Authorization", "Bearer "+token.AccessToken)
|
req.Header.Set("Authorization", "Bearer "+token.AccessToken)
|
||||||
client := &http.Client{}
|
client := &http.Client{Timeout: 10 * time.Second}
|
||||||
userResp, err := client.Do(req)
|
userResp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get user info: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||||
http.Error(w, "Failed to get user info", http.StatusInternalServerError)
|
http.Error(w, "Failed to get user info", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer userResp.Body.Close()
|
defer userResp.Body.Close()
|
||||||
|
|
||||||
|
// 检查用户信息响应状态码
|
||||||
|
if userResp.StatusCode != http.StatusOK {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> %d (%s) userinfo endpoint returned error status: %s from %s",
|
||||||
|
r.Method, r.URL.Path, userResp.StatusCode, utils.GetClientIP(r), userResp.Status, utils.GetRequestSource(r))
|
||||||
|
http.Error(w, "Failed to get user info: "+userResp.Status, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var userInfo OAuthUserInfo
|
var userInfo OAuthUserInfo
|
||||||
if err := json.NewDecoder(userResp.Body).Decode(&userInfo); err != nil {
|
if err := json.NewDecoder(userResp.Body).Decode(&userInfo); err != nil {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to parse user info: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||||
http.Error(w, "Failed to parse user info", http.StatusInternalServerError)
|
http.Error(w, "Failed to parse user info", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验证用户信息
|
||||||
|
if userInfo.Username == "" {
|
||||||
|
log.Printf("[Auth] ERR %s %s -> 500 (%s) received invalid user info (missing username) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||||
|
http.Error(w, "Invalid user information", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 生成内部访问令牌
|
// 生成内部访问令牌
|
||||||
internalToken := h.auth.generateToken()
|
internalToken := h.auth.generateToken()
|
||||||
h.auth.addToken(internalToken, userInfo.Username, tokenExpiry)
|
h.auth.addToken(internalToken, userInfo.Username, tokenExpiry)
|
||||||
|
|
||||||
|
log.Printf("[Auth] %s %s -> 200 (%s) login success for user %s from %s", r.Method, r.URL.Path, utils.GetClientIP(r), userInfo.Username, utils.GetRequestSource(r))
|
||||||
|
|
||||||
// 返回登录成功页面
|
// 返回登录成功页面
|
||||||
w.Header().Set("Content-Type", "text/html")
|
w.Header().Set("Content-Type", "text/html")
|
||||||
fmt.Fprintf(w, `
|
fmt.Fprintf(w, `
|
||||||
|
Loading…
x
Reference in New Issue
Block a user