mirror of https://github.com/Xhofe/alist
				
				
				
			perf: sha256 for user's password (close #3552)
							parent
							
								
									30415cefbe
								
							
						
					
					
						commit
						75acbcc115
					
				|  | @ -26,17 +26,17 @@ func initUser() { | |||
| 		if errors.Is(err, gorm.ErrRecordNotFound) { | ||||
| 			admin = &model.User{ | ||||
| 				Username: "admin", | ||||
| 				Password: adminPassword, | ||||
| 				PwdHash:  model.HashPwd(adminPassword), | ||||
| 				Role:     model.ADMIN, | ||||
| 				BasePath: "/", | ||||
| 			} | ||||
| 			if err := op.CreateUser(admin); err != nil { | ||||
| 				panic(err) | ||||
| 			} else { | ||||
| 				utils.Log.Infof("Successfully created the admin user and the initial password is: %s", admin.Password) | ||||
| 				utils.Log.Infof("Successfully created the admin user and the initial password is: %s", adminPassword) | ||||
| 			} | ||||
| 		} else { | ||||
| 			panic(err) | ||||
| 			utils.Log.Fatalf("[init user] Failed to get admin user: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 	guest, err := op.GetGuest() | ||||
|  | @ -44,17 +44,34 @@ func initUser() { | |||
| 		if errors.Is(err, gorm.ErrRecordNotFound) { | ||||
| 			guest = &model.User{ | ||||
| 				Username:   "guest", | ||||
| 				Password:   "guest", | ||||
| 				PwdHash:    model.HashPwd("guest"), | ||||
| 				Role:       model.GUEST, | ||||
| 				BasePath:   "/", | ||||
| 				Permission: 0, | ||||
| 				Disabled:   true, | ||||
| 			} | ||||
| 			if err := db.CreateUser(guest); err != nil { | ||||
| 				panic(err) | ||||
| 				utils.Log.Fatalf("[init user] Failed to create guest user: %v", err) | ||||
| 			} | ||||
| 		} else { | ||||
| 			panic(err) | ||||
| 			utils.Log.Fatalf("[init user] Failed to get guest user: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 	hashPwdForOldVersion() | ||||
| } | ||||
| 
 | ||||
| func hashPwdForOldVersion() { | ||||
| 	users, _, err := op.GetUsers(1, -1) | ||||
| 	if err != nil { | ||||
| 		utils.Log.Fatalf("[hash pwd for old version] failed get users: %v", err) | ||||
| 	} | ||||
| 	for i := range users { | ||||
| 		user := users[i] | ||||
| 		if user.PwdHash == "" { | ||||
| 			user.PwdHash = model.HashPwd(user.Password) | ||||
| 			if err := db.UpdateUser(&user); err != nil { | ||||
| 				utils.Log.Fatalf("[hash pwd for old version] failed update user: %v", err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| package model | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/alist-org/alist/v3/internal/errs" | ||||
| 	"github.com/alist-org/alist/v3/pkg/utils" | ||||
| 	"github.com/pkg/errors" | ||||
|  | @ -12,10 +14,13 @@ const ( | |||
| 	ADMIN | ||||
| ) | ||||
| 
 | ||||
| const HashSalt = "https://github.com/alist-org/alist" | ||||
| 
 | ||||
| type User struct { | ||||
| 	ID       uint   `json:"id" gorm:"primaryKey"`                      // unique key
 | ||||
| 	Username string `json:"username" gorm:"unique" binding:"required"` // username
 | ||||
| 	Password string `json:"password"`                                  // password
 | ||||
| 	PwdHash  string `json:"-"`                                         // password hash
 | ||||
| 	Password string `json:"-"`                                         // password
 | ||||
| 	BasePath string `json:"base_path"`                                 // base path
 | ||||
| 	Role     int    `json:"role"`                                      // user's role
 | ||||
| 	Disabled bool   `json:"disabled"` | ||||
|  | @ -45,10 +50,14 @@ func (u User) IsAdmin() bool { | |||
| } | ||||
| 
 | ||||
| func (u User) ValidatePassword(password string) error { | ||||
| 	if password == "" { | ||||
| 	return u.ValidatePwdHash(HashPwd(password)) | ||||
| } | ||||
| 
 | ||||
| func (u User) ValidatePwdHash(pwdHash string) error { | ||||
| 	if pwdHash == "" { | ||||
| 		return errors.WithStack(errs.EmptyPassword) | ||||
| 	} | ||||
| 	if u.Password != password { | ||||
| 	if u.PwdHash != pwdHash { | ||||
| 		return errors.WithStack(errs.WrongPassword) | ||||
| 	} | ||||
| 	return nil | ||||
|  | @ -101,3 +110,7 @@ func (u User) CanAddQbittorrentTasks() bool { | |||
| func (u User) JoinPath(reqPath string) (string, error) { | ||||
| 	return utils.JoinBasePath(u.BasePath, reqPath) | ||||
| } | ||||
| 
 | ||||
| func HashPwd(password string) string { | ||||
| 	return utils.GetSHA256Encode([]byte(fmt.Sprintf("%s-%s", password, HashSalt))) | ||||
| } | ||||
|  |  | |||
|  | @ -28,6 +28,26 @@ type LoginReq struct { | |||
| 
 | ||||
| // Login Deprecated
 | ||||
| func Login(c *gin.Context) { | ||||
| 	var req LoginReq | ||||
| 	if err := c.ShouldBind(&req); err != nil { | ||||
| 		common.ErrorResp(c, err, 400) | ||||
| 		return | ||||
| 	} | ||||
| 	req.Password = model.HashPwd(req.Password) | ||||
| 	loginHash(c, &req) | ||||
| } | ||||
| 
 | ||||
| // LoginHash login with password hashed by sha256
 | ||||
| func LoginHash(c *gin.Context) { | ||||
| 	var req LoginReq | ||||
| 	if err := c.ShouldBind(&req); err != nil { | ||||
| 		common.ErrorResp(c, err, 400) | ||||
| 		return | ||||
| 	} | ||||
| 	loginHash(c, &req) | ||||
| } | ||||
| 
 | ||||
| func loginHash(c *gin.Context, req *LoginReq) { | ||||
| 	// check count of login
 | ||||
| 	ip := c.ClientIP() | ||||
| 	count, ok := loginCache.Get(ip) | ||||
|  | @ -37,19 +57,14 @@ func Login(c *gin.Context) { | |||
| 		return | ||||
| 	} | ||||
| 	// check username
 | ||||
| 	var req LoginReq | ||||
| 	if err := c.ShouldBind(&req); err != nil { | ||||
| 		common.ErrorResp(c, err, 400) | ||||
| 		return | ||||
| 	} | ||||
| 	user, err := op.GetUserByName(req.Username) | ||||
| 	if err != nil { | ||||
| 		common.ErrorResp(c, err, 400) | ||||
| 		loginCache.Set(ip, count+1) | ||||
| 		return | ||||
| 	} | ||||
| 	// validate password
 | ||||
| 	if err := user.ValidatePassword(req.Password); err != nil { | ||||
| 	// validate password hash
 | ||||
| 	if err := user.ValidatePwdHash(req.Password); err != nil { | ||||
| 		common.ErrorResp(c, err, 400) | ||||
| 		loginCache.Set(ip, count+1) | ||||
| 		return | ||||
|  |  | |||
|  | @ -46,6 +46,7 @@ func Init(e *gin.Engine) { | |||
| 	auth := api.Group("", middlewares.Auth) | ||||
| 
 | ||||
| 	api.POST("/auth/login", handles.Login) | ||||
| 	api.POST("/auth/login/hash", handles.LoginHash) | ||||
| 	auth.GET("/me", handles.CurrentUser) | ||||
| 	auth.POST("/me/update", handles.UpdateCurrent) | ||||
| 	auth.POST("/auth/2fa/generate", handles.Generate2FA) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Andy Hsu
						Andy Hsu