package isapi import ( "bytes" "io/ioutil" "net/http" ) // AuthTransport 实现接口http.RoundTripper,自定义RoundTripper处理认证 type AuthTransport struct { Username string Password string Transport http.RoundTripper } func NewAuthTransport(username, password string) *AuthTransport { t := &AuthTransport{ Username: username, Password: password, } t.Transport = http.DefaultTransport return t } func (t *AuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { req2 := new(http.Request) *req2 = *req //复制header req2.Header = make(http.Header) for k, s := range req.Header { req2.Header[k] = s } // 复制body if req.Body != nil { buf, _ := ioutil.ReadAll(req.Body) req.Body = ioutil.NopCloser(bytes.NewBuffer(buf)) req2.Body = ioutil.NopCloser(bytes.NewBuffer(buf)) } // resp, err := t.Transport.RoundTrip(req) if err != nil || resp.StatusCode != 401 { return resp, err } //↓未认证逻辑----------- authChal := resp.Header.Get("WWW-Authenticate") c := NewChallenge(authChal) authResp := c.Authorize(t.Username, t.Password, req.Method, req.URL.Path) resp.Body.Close() //todo nonce并未重用,可以优化 req2.Header.Set("Authorization", authResp.String()) return t.Transport.RoundTrip(req2) }