http.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. package isapi
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "net/http"
  6. )
  7. // AuthTransport 实现接口http.RoundTripper,自定义RoundTripper处理认证
  8. type AuthTransport struct {
  9. Username string
  10. Password string
  11. Transport http.RoundTripper
  12. }
  13. func NewAuthTransport(username, password string) *AuthTransport {
  14. t := &AuthTransport{
  15. Username: username,
  16. Password: password,
  17. }
  18. t.Transport = http.DefaultTransport
  19. return t
  20. }
  21. func (t *AuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
  22. req2 := new(http.Request)
  23. *req2 = *req
  24. //复制header
  25. req2.Header = make(http.Header)
  26. for k, s := range req.Header {
  27. req2.Header[k] = s
  28. }
  29. // 复制body
  30. if req.Body != nil {
  31. buf, _ := ioutil.ReadAll(req.Body)
  32. req.Body = ioutil.NopCloser(bytes.NewBuffer(buf))
  33. req2.Body = ioutil.NopCloser(bytes.NewBuffer(buf))
  34. }
  35. //
  36. resp, err := t.Transport.RoundTrip(req)
  37. if err != nil || resp.StatusCode != 401 {
  38. return resp, err
  39. }
  40. //↓未认证逻辑-----------
  41. authChal := resp.Header.Get("WWW-Authenticate")
  42. c := NewChallenge(authChal)
  43. authResp := c.Authorize(t.Username, t.Password, req.Method, req.URL.Path)
  44. resp.Body.Close()
  45. //todo nonce并未重用,可以优化
  46. req2.Header.Set("Authorization", authResp.String())
  47. return t.Transport.RoundTrip(req2)
  48. }