Files
v2ray_simple/utils/user.go
e1732a364fed 3d80f6a305 令smux+simplesocks支持user分流;fix #217
通过在utils添加 UserAssigner接口, 并在此用例时调用SetUser来达到目的
2022-12-27 19:41:42 +08:00

353 lines
7.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package utils
import (
"bytes"
"net/url"
"sync"
)
// User是一个 可确定唯一身份,且可验证该身份的 标识。
type User interface {
IdentityStr() string //每个user唯一通过比较这个string 即可 判断两个User 是否相等。相当于 user name
IdentityBytes() []byte //与str类似; 对于程序来说,bytes更方便处理; 可以与str相同也可以不同.
AuthStr() string //AuthStr 可以识别出该用户 并验证该User的真实性。相当于 user name + password
AuthBytes() []byte //与 AuthStr 类似
}
type UserWithPass interface {
User
GetPassword() []byte
}
// 用户集合,判断用户是否存在并取出
type UserSet interface {
HasUserByBytes(bs []byte) User
IDBytesLen() int //用户名bytes的最小长度
}
// 通过验证信息 试图取出 一个User
type UserAuthenticator interface {
AuthUserByStr(authStr string) User
AuthUserByBytes(authBytes []byte) User
AuthBytesLen() int
}
// 用户容器,可判断是否存在,也可以验证
type UserContainer interface {
UserSet
UserAuthenticator
}
// 可以控制 User 登入和登出 的接口
type UserBus interface {
AddUser(User) error
DelUser(User)
}
type UserAssigner interface {
SetUser(User)
}
type UserConf struct {
User string `toml:"user"`
Pass string `toml:"pass"`
}
func InitV2rayUsers(uc []UserConf) (us []User) {
us = make([]User, len(uc))
for i, theuc := range uc {
var vu V2rayUser
copy(vu[:], StrToUUID_slice(theuc.User))
us[i] = vu
}
return
}
func InitRealV2rayUsers(uc []UserConf) (us []V2rayUser) {
us = make([]V2rayUser, len(uc))
for i, theuc := range uc {
var vu V2rayUser
copy(vu[:], StrToUUID_slice(theuc.User))
us[i] = vu
}
return
}
// 一种专门用于v2ray协议族(vmess/vless)的 用于标识用户的符号 , 实现 User 接口. (其实就是uuid)
type V2rayUser [UUID_BytesLen]byte
func (u V2rayUser) IdentityStr() string {
return UUIDToStr(u[:])
}
func (u V2rayUser) AuthStr() string {
return u.IdentityStr()
}
func (u V2rayUser) IdentityBytes() []byte {
return u[:]
}
func (u V2rayUser) AuthBytes() []byte {
return u[:]
}
func NewV2rayUser(uuidStr string) (V2rayUser, error) {
uuid, err := StrToUUID(uuidStr)
if err != nil {
return V2rayUser{}, err
}
return V2rayUser(uuid), nil
}
// used in proxy/socks5 and proxy.http. implements User
type UserPass struct {
UserID, Password []byte
}
func NewUserPass(uc UserConf) *UserPass {
return &UserPass{
UserID: []byte(uc.User),
Password: []byte(uc.Pass),
}
}
func NewUserPassByData(user, pass []byte) *UserPass {
return &UserPass{
UserID: user,
Password: pass,
}
}
func (ph *UserPass) IdentityStr() string {
return string(ph.UserID)
}
func (ph *UserPass) IdentityBytes() []byte {
return ph.UserID
}
func (ph *UserPass) AuthStr() string {
return string(ph.UserID) + "\n" + string(ph.Password)
}
func (ph *UserPass) AuthBytes() []byte {
return []byte(ph.AuthStr())
}
// return len(ph.User) > 0 && len(ph.Password) > 0
func (ph *UserPass) Valid() bool {
return len(ph.UserID) > 0 && len(ph.Password) > 0
}
func (ph *UserPass) GetUserByPass(user, pass []byte) User {
if bytes.Equal(user, ph.UserID) && bytes.Equal(pass, ph.Password) {
return ph
}
return nil
}
func (ph *UserPass) AuthUserByStr(idStr string) User {
if idStr == ph.AuthStr() {
return ph
}
return nil
}
func (ph *UserPass) AuthUserByBytes(bs []byte) User {
if bytes.Equal(bs, ph.AuthBytes()) {
return ph
}
return nil
}
// require "user" and "pass" field. return true if both not empty.
func (ph *UserPass) InitWithUrl(u *url.URL) bool {
ph.UserID = []byte(u.Query().Get("user"))
ph.Password = []byte(u.Query().Get("pass"))
return len(ph.UserID) > 0 && len(ph.Password) > 0
}
// uuid: "user:xxxx\npass:xxxx"
func (ph *UserPass) InitWithStr(str string) (ok bool) {
var v1, v2 string
ok, v1, v2 = CommonSplit(str, "user", "pass")
if !ok {
return
}
ph.UserID = []byte(v1)
ph.Password = []byte(v2)
return
}
// implements UserBus, UserSet, UserGetter; 只能存储同一类型的User.
// 通过 bytes存储用户id而不是 str。
type MultiUserMap struct {
IDMap map[string]User
AuthMap map[string]User
Mutex sync.RWMutex
TheIDBytesLen, TheAuthBytesLen int
StoreKeyByStr bool //如果这一项给出, 则内部会用 identityStr/AuthStr 作为key;否则会用 string(identityBytes) 或 string(AuthBytes) 作为key
IDStrToBytesFunc func(string) []byte
IDBytesToStrFunc func([]byte) string //必须与 Key_StrToBytesFunc 同时给出
AuthStrToBytesFunc func(string) []byte
AuthBytesToStrFunc func([]byte) string //必须与 Key_AuthStrToBytesFunc 同时给出
}
func NewMultiUserMap() *MultiUserMap {
mup := &MultiUserMap{
IDMap: make(map[string]User),
AuthMap: make(map[string]User),
}
return mup
}
func (mu *MultiUserMap) SetUseUUIDStr_asKey() {
//uuid 既是 id 又是 auth
mu.StoreKeyByStr = true
mu.TheIDBytesLen = UUID_BytesLen
mu.TheAuthBytesLen = UUID_BytesLen
mu.IDBytesToStrFunc = UUIDToStr
mu.AuthBytesToStrFunc = UUIDToStr
mu.IDStrToBytesFunc = StrToUUID_slice
mu.AuthStrToBytesFunc = StrToUUID_slice
}
// same as AddUser_nolock but with lock; concurrent safe
func (mu *MultiUserMap) AddUser(u User) error {
mu.Mutex.Lock()
mu.AddUser_nolock(u)
mu.Mutex.Unlock()
return nil
}
// not concurrent safe, use with caution.
func (mu *MultiUserMap) AddUser_nolock(u User) {
if mu.StoreKeyByStr {
mu.IDMap[u.IdentityStr()] = u
mu.AuthMap[u.AuthStr()] = u
} else {
mu.IDMap[string(u.IdentityBytes())] = u
mu.AuthMap[string(u.AuthBytes())] = u
}
}
func (mu *MultiUserMap) DelUser(u User) error {
mu.Mutex.Lock()
if mu.StoreKeyByStr {
delete(mu.IDMap, u.AuthStr())
delete(mu.AuthMap, u.IdentityStr())
} else {
delete(mu.IDMap, string(u.AuthBytes()))
delete(mu.AuthMap, string(u.IdentityBytes()))
}
mu.Mutex.Unlock()
return nil
}
func (mu *MultiUserMap) LoadUsers(us []User) {
mu.Mutex.Lock()
defer mu.Mutex.Unlock()
for _, u := range us {
mu.AddUser_nolock(u)
}
}
// 通过ID查找
func (mu *MultiUserMap) HasUserByStr(str string) bool {
mu.Mutex.RLock()
defer mu.Mutex.RUnlock()
if !mu.StoreKeyByStr && mu.IDStrToBytesFunc != nil {
return mu.IDMap[string(mu.IDStrToBytesFunc(str))] != nil
} else {
return mu.IDMap[str] != nil
}
}
// 通过ID查找
func (mu *MultiUserMap) HasUserByBytes(bs []byte) User {
mu.Mutex.RLock()
defer mu.Mutex.RUnlock()
if mu.StoreKeyByStr && mu.IDBytesToStrFunc != nil {
return mu.IDMap[mu.IDBytesToStrFunc(bs)]
} else {
return mu.IDMap[string(bs)]
}
}
func (mu *MultiUserMap) IDBytesLen() int {
return mu.TheIDBytesLen
}
func (mu *MultiUserMap) AuthBytesLen() int {
return mu.TheAuthBytesLen
}
// 通过Auth查找
func (mu *MultiUserMap) AuthUserByStr(str string) User {
mu.Mutex.RLock()
var u User
if !mu.StoreKeyByStr && mu.AuthStrToBytesFunc != nil {
u = mu.AuthMap[string(mu.AuthStrToBytesFunc(str))]
} else {
u = mu.AuthMap[str]
}
mu.Mutex.RUnlock()
return u
}
// 通过Auth查找
func (mu *MultiUserMap) AuthUserByBytes(bs []byte) User {
mu.Mutex.RLock()
var u User
if mu.StoreKeyByStr && mu.AuthBytesToStrFunc != nil {
u = mu.AuthMap[mu.AuthBytesToStrFunc(bs)]
} else {
u = mu.AuthMap[string(bs)]
}
mu.Mutex.RUnlock()
return u
}