github.com/cnotch/ipchub@v1.1.0/provider/auth/user.go (about) 1 // Copyright (c) 2019,CAOHONGJU All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package auth 6 7 import ( 8 "crypto/md5" 9 "encoding/hex" 10 "errors" 11 "strings" 12 13 "github.com/cnotch/ipchub/utils/scan" 14 ) 15 16 // AccessRight 访问权限类型 17 type AccessRight int 18 19 // 权限常量 20 const ( 21 PullRight AccessRight = 1 << iota // 拉流权限 22 PushRight // 推流权限 23 ) 24 25 // UserProvider 用户提供者 26 type UserProvider interface { 27 LoadAll() ([]*User, error) 28 Flush(full []*User, saves []*User, removes []*User) error 29 } 30 31 // User 用户 32 type User struct { 33 Name string `json:"name"` 34 Password string `json:"password,omitempty"` 35 Admin bool `json:"admin,omitempty"` 36 PushAccess string `json:"push,omitempty"` 37 PullAccess string `json:"pull,omitempty"` 38 39 pushMatchers []PathMatcher 40 pullMatchers []PathMatcher 41 } 42 43 func initMatchers(access string, destMatcher *[]PathMatcher) { 44 advance := access 45 pathMask := "" 46 continueScan := true 47 for continueScan { 48 advance, pathMask, continueScan = scan.Semicolon.Scan(advance) 49 if len(pathMask) == 0 { 50 continue 51 } 52 *destMatcher = append(*destMatcher, NewPathMatcher(pathMask)) 53 } 54 } 55 56 func (u *User) init() error { 57 u.Name = strings.ToLower(u.Name) 58 if u.Admin { 59 if len(u.PullAccess) == 0 { 60 u.PullAccess = "*" 61 } 62 if len(u.PushAccess) == 0 { 63 u.PushAccess = "*" 64 } 65 } 66 67 initMatchers(u.PushAccess, &u.pushMatchers) 68 initMatchers(u.PullAccess, &u.pullMatchers) 69 return nil 70 } 71 72 // PasswordMD5 返回口令的MD5字串 73 func (u *User) PasswordMD5() string { 74 if passwordNeedMD5(u.Password) { 75 pw := md5.Sum([]byte(u.Password)) 76 return hex.EncodeToString(pw[:]) 77 } 78 return u.Password 79 } 80 81 // ValidatePassword 验证密码 82 func (u *User) ValidatePassword(password string) error { 83 if passwordNeedMD5(password) { 84 pw := md5.Sum([]byte(password)) 85 password = hex.EncodeToString(pw[:]) 86 } 87 88 if strings.EqualFold(u.PasswordMD5(), password) { 89 return nil 90 } 91 return errors.New("password error") 92 } 93 94 // ValidatePermission 验证权限 95 func (u *User) ValidatePermission(path string, right AccessRight) bool { 96 var matchers []PathMatcher 97 switch right { 98 case PushRight: 99 matchers = u.pushMatchers 100 case PullRight: 101 matchers = u.pullMatchers 102 } 103 104 if matchers == nil { 105 return false 106 } 107 108 path = strings.TrimSpace(path) 109 for _, matcher := range matchers { 110 if matcher.Match(path) { 111 return true 112 } 113 } 114 115 return false 116 } 117 118 // CopyFrom 从源属性并初始化 119 func (u *User) CopyFrom(src *User, withPassword bool) { 120 if withPassword { 121 u.Password = src.Password 122 } 123 u.Admin = src.Admin 124 u.PushAccess = src.PushAccess 125 u.PullAccess = src.PullAccess 126 u.init() 127 } 128 129 // 密码是否需要进行md5处理,如果已经是md5则不处理 130 func passwordNeedMD5(password string) bool { 131 if len(password) != 32 { 132 return true 133 } 134 135 _, err := hex.DecodeString(password) 136 if err != nil { 137 return true 138 } 139 140 return false 141 }