| |
| |
| |
|
|
| package auth |
|
|
| import ( |
| "log" |
| "sync" |
|
|
| "github.com/GoAdminGroup/go-admin/modules/db/dialect" |
| "github.com/GoAdminGroup/go-admin/modules/logger" |
|
|
| "github.com/GoAdminGroup/go-admin/context" |
| "github.com/GoAdminGroup/go-admin/modules/db" |
| "github.com/GoAdminGroup/go-admin/modules/service" |
| "github.com/GoAdminGroup/go-admin/plugins/admin/models" |
| "github.com/GoAdminGroup/go-admin/plugins/admin/modules" |
| "golang.org/x/crypto/bcrypt" |
| ) |
|
|
| |
| func Auth(ctx *context.Context) models.UserModel { |
| return ctx.User().(models.UserModel) |
| } |
|
|
| |
| func Check(password string, username string, conn db.Connection) (user models.UserModel, ok bool) { |
|
|
| user = models.User().SetConn(conn).FindByUserName(username) |
|
|
| if user.IsEmpty() { |
| ok = false |
| } else { |
| if comparePassword(password, user.Password) { |
| ok = true |
| user = user.WithRoles().WithPermissions().WithMenus() |
| user.UpdatePwd(EncodePassword([]byte(password))) |
| } else { |
| ok = false |
| } |
| } |
| return |
| } |
|
|
| func comparePassword(comPwd, pwdHash string) bool { |
| err := bcrypt.CompareHashAndPassword([]byte(pwdHash), []byte(comPwd)) |
| return err == nil |
| } |
|
|
| |
| func EncodePassword(pwd []byte) string { |
| hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost) |
| if err != nil { |
| return "" |
| } |
| return string(hash) |
| } |
|
|
| |
| func SetCookie(ctx *context.Context, user models.UserModel, conn db.Connection) error { |
| ses, err := InitSession(ctx, conn) |
|
|
| if err != nil { |
| return err |
| } |
|
|
| return ses.Add("user_id", user.Id) |
| } |
|
|
| |
| func DelCookie(ctx *context.Context, conn db.Connection) error { |
| ses, err := InitSession(ctx, conn) |
|
|
| if err != nil { |
| return err |
| } |
|
|
| return ses.Clear() |
| } |
|
|
| type TokenService struct { |
| tokens CSRFToken |
| lock sync.Mutex |
| conn db.Connection |
| } |
|
|
| func (s *TokenService) Name() string { |
| return TokenServiceKey |
| } |
|
|
| func InitCSRFTokenSrv(conn db.Connection) (string, service.Service) { |
| list, err := db.WithDriver(conn).Table("goadmin_session"). |
| Where("values", "=", "__csrf_token__"). |
| All() |
| if db.CheckError(err, db.QUERY) { |
| logger.Error("csrf token query from database error: ", err) |
| } |
| tokens := make(CSRFToken, len(list)) |
| for i := 0; i < len(list); i++ { |
| tokens[i] = list[i]["sid"].(string) |
| } |
| return TokenServiceKey, &TokenService{ |
| tokens: tokens, |
| conn: conn, |
| } |
| } |
|
|
| const ( |
| TokenServiceKey = "token_csrf_helper" |
| ServiceKey = "auth" |
| ) |
|
|
| func GetTokenService(s interface{}) *TokenService { |
| if srv, ok := s.(*TokenService); ok { |
| return srv |
| } |
| log.Panicf("wrong service: %+v", s) |
| return nil |
| } |
|
|
| |
| func (s *TokenService) AddToken() string { |
| s.lock.Lock() |
| defer s.lock.Unlock() |
| tokenStr := modules.Uuid() |
| s.tokens = append(s.tokens, tokenStr) |
| _, err := db.WithDriver(s.conn).Table("goadmin_session").Insert(dialect.H{ |
| "sid": tokenStr, |
| "values": "__csrf_token__", |
| }) |
| if db.CheckError(err, db.INSERT) { |
| logger.Error("csrf token insert into database error: ", err) |
| } |
| return tokenStr |
| } |
|
|
| |
| |
| func (s *TokenService) CheckToken(toCheckToken string) (ok bool) { |
| defer func() { |
| if ok { |
| err := db.WithDriver(s.conn).Table("goadmin_session"). |
| Where("sid", "=", toCheckToken). |
| Where("values", "=", "__csrf_token__"). |
| Delete() |
| if db.CheckError(err, db.DELETE) { |
| logger.Error("csrf token delete from database error: ", err) |
| } |
| } |
| }() |
|
|
| for i := 0; i < len(s.tokens); i++ { |
| if (s.tokens)[i] == toCheckToken { |
| s.tokens = append((s.tokens)[:i], (s.tokens)[i+1:]...) |
| ok = true |
| return |
| } |
| } |
|
|
| item, err := db.WithDriver(s.conn).Table("goadmin_session"). |
| Where("sid", "=", toCheckToken). |
| Where("values", "=", "__csrf_token__"). |
| First() |
| if item != nil && err == nil { |
| ok = true |
| return |
| } |
| return |
| } |
|
|
| |
| type CSRFToken []string |
|
|
| type Processor func(ctx *context.Context) (model models.UserModel, exist bool, msg string) |
|
|
| type Service struct { |
| P Processor |
| } |
|
|
| func (s *Service) Name() string { |
| return "auth" |
| } |
|
|
| func GetService(s interface{}) *Service { |
| if srv, ok := s.(*Service); ok { |
| return srv |
| } |
| log.Panicf("wrong service: %+v", s) |
| return nil |
| } |
|
|
| func NewService(processor Processor) *Service { |
| return &Service{ |
| P: processor, |
| } |
| } |
|
|