basic.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Public Domain Software
  3. *
  4. * I (Matthias Ladkau) am the author of the source code in this file.
  5. * I have placed the source code in this file in the public domain.
  6. *
  7. * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
  8. */
  9. package auth
  10. import (
  11. "encoding/base64"
  12. "net/http"
  13. "strings"
  14. "devt.de/krotik/common/httputil/user"
  15. )
  16. /*
  17. Realm is the authentication realm
  18. */
  19. var Realm = "RestrictedAccessRealm"
  20. /*
  21. BashicAuthHandleFuncWrapper datastructure. Wrapper for HandleFunc to add
  22. basic authentication to all added endpoints.
  23. */
  24. type BashicAuthHandleFuncWrapper struct {
  25. origHandleFunc func(pattern string, handler func(http.ResponseWriter, *http.Request))
  26. authFunc func(user, pass string) bool
  27. accessFunc func(http.ResponseWriter, *http.Request, string) bool
  28. // Callbacks
  29. CallbackSessionExpired func(w http.ResponseWriter, r *http.Request)
  30. CallbackUnauthorized func(w http.ResponseWriter, r *http.Request)
  31. }
  32. /*
  33. NewBashicAuthHandleFuncWrapper creates a new HandleFunc wrapper.
  34. */
  35. func NewBashicAuthHandleFuncWrapper(origHandleFunc func(pattern string,
  36. handler func(http.ResponseWriter, *http.Request))) *BashicAuthHandleFuncWrapper {
  37. return &BashicAuthHandleFuncWrapper{
  38. origHandleFunc,
  39. nil,
  40. nil,
  41. // Session expired callback
  42. func(w http.ResponseWriter, r *http.Request) {
  43. w.Header().Set("WWW-Authenticate", `Basic realm="`+Realm+`"`)
  44. w.WriteHeader(http.StatusUnauthorized)
  45. w.Write([]byte("Session expired\n"))
  46. },
  47. func(w http.ResponseWriter, r *http.Request) {
  48. w.Header().Set("WWW-Authenticate", `Basic realm="`+Realm+`"`)
  49. w.WriteHeader(http.StatusUnauthorized)
  50. w.Write([]byte("Unauthorized\n"))
  51. },
  52. }
  53. }
  54. /*
  55. SetAuthFunc gives an authentication function which can be used by the wrapper
  56. to authenticate users.
  57. */
  58. func (bw *BashicAuthHandleFuncWrapper) SetAuthFunc(authFunc func(user, pass string) bool) {
  59. bw.authFunc = authFunc
  60. }
  61. /*
  62. SetAccessFunc sets an access function which can be used by the wrapper to
  63. check the user access rights.
  64. */
  65. func (bw *BashicAuthHandleFuncWrapper) SetAccessFunc(accessFunc func(http.ResponseWriter, *http.Request, string) bool) {
  66. bw.accessFunc = accessFunc
  67. }
  68. /*
  69. HandleFunc is the new handle func which wraps an original handle functions to do an authentication check.
  70. */
  71. func (bw *BashicAuthHandleFuncWrapper) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
  72. bw.origHandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
  73. if name, res := bw.CheckAuth(r); res {
  74. session, err := user.UserSessionManager.GetSession(name, w, r, true)
  75. if session != nil && err == nil {
  76. // Check authorization
  77. if bw.accessFunc == nil || bw.accessFunc(w, r, name) {
  78. // Handle the request
  79. handler(w, r)
  80. }
  81. return
  82. }
  83. bw.CallbackSessionExpired(w, r)
  84. return
  85. }
  86. bw.CallbackUnauthorized(w, r)
  87. })
  88. }
  89. /*
  90. CheckAuth checks the user authentication of an incomming request. Returns
  91. if the authentication is correct and the given username.
  92. */
  93. func (bw *BashicAuthHandleFuncWrapper) CheckAuth(r *http.Request) (string, bool) {
  94. var user string
  95. var ok bool
  96. if s := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(s) == 2 {
  97. if b, err := base64.StdEncoding.DecodeString(s[1]); err == nil {
  98. if pair := strings.Split(string(b), ":"); len(pair) == 2 {
  99. user = pair[0]
  100. pass := pair[1]
  101. ok = bw.authFunc != nil && bw.authFunc(user, pass)
  102. }
  103. }
  104. }
  105. return user, ok
  106. }