From 4c919de552f2df5f02f432a030f315c4bf62a153 Mon Sep 17 00:00:00 2001 From: laodaming <11058467+laudamine@user.noreply.gitee.com> Date: Tue, 21 Nov 2023 17:08:22 +0800 Subject: [PATCH] fix --- .../internal/handler/ldapuserloginhandler.go | 35 ++++++++ server/ldap-admin/internal/handler/routes.go | 5 ++ .../internal/logic/ldapuserloginlogic.go | 82 +++++++++++++++++++ server/ldap-admin/internal/types/types.go | 9 ++ server_api/ldap-admin.api | 11 +++ utils/ldap_lib/jwt_parse.go | 51 ++++++++++++ 6 files changed, 193 insertions(+) create mode 100644 server/ldap-admin/internal/handler/ldapuserloginhandler.go create mode 100644 server/ldap-admin/internal/logic/ldapuserloginlogic.go create mode 100644 utils/ldap_lib/jwt_parse.go diff --git a/server/ldap-admin/internal/handler/ldapuserloginhandler.go b/server/ldap-admin/internal/handler/ldapuserloginhandler.go new file mode 100644 index 00000000..e9ee6041 --- /dev/null +++ b/server/ldap-admin/internal/handler/ldapuserloginhandler.go @@ -0,0 +1,35 @@ +package handler + +import ( + "net/http" + "reflect" + + "fusenapi/utils/basic" + + "fusenapi/server/ldap-admin/internal/logic" + "fusenapi/server/ldap-admin/internal/svc" + "fusenapi/server/ldap-admin/internal/types" +) + +func LdapUserLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + + var req types.LdapUserLoginReq + userinfo, err := basic.RequestParse(w, r, svcCtx, &req) + if err != nil { + return + } + + // 创建一个业务逻辑层实例 + l := logic.NewLdapUserLoginLogic(r.Context(), svcCtx) + + rl := reflect.ValueOf(l) + basic.BeforeLogic(w, r, rl) + + resp := l.LdapUserLogin(&req, userinfo) + + if !basic.AfterLogic(w, r, rl, resp) { + basic.NormalAfterLogic(w, r, resp) + } + } +} diff --git a/server/ldap-admin/internal/handler/routes.go b/server/ldap-admin/internal/handler/routes.go index 3cd84f8e..c3181566 100644 --- a/server/ldap-admin/internal/handler/routes.go +++ b/server/ldap-admin/internal/handler/routes.go @@ -147,6 +147,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/api/ldap-admin/get_ldap_users", Handler: GetLdapUsersHandler(serverCtx), }, + { + Method: http.MethodPost, + Path: "/api/ldap-admin/ldap_user_login", + Handler: LdapUserLoginHandler(serverCtx), + }, }, ) } diff --git a/server/ldap-admin/internal/logic/ldapuserloginlogic.go b/server/ldap-admin/internal/logic/ldapuserloginlogic.go new file mode 100644 index 00000000..f68466ea --- /dev/null +++ b/server/ldap-admin/internal/logic/ldapuserloginlogic.go @@ -0,0 +1,82 @@ +package logic + +import ( + "fmt" + "fusenapi/utils/auth" + "fusenapi/utils/basic" + "fusenapi/utils/email" + "fusenapi/utils/encryption_decryption" + "fusenapi/utils/ldap_lib" + "strings" + + "context" + + "fusenapi/server/ldap-admin/internal/svc" + "fusenapi/server/ldap-admin/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type LdapUserLoginLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewLdapUserLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LdapUserLoginLogic { + return &LdapUserLoginLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +// 处理进入前逻辑w,r +// func (l *LdapUserLoginLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) { +// } + +func (l *LdapUserLoginLogic) LdapUserLogin(req *types.LdapUserLoginReq, userinfo *auth.UserInfo) (resp *basic.Response) { + req.Email = strings.Trim(req.Email, " ") + req.Password = strings.Trim(req.Password, " ") + if !email.IsEmailValid(req.Email) { + return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "邮箱格式不正确") + } + userDN := fmt.Sprintf("cn=%s,%s", req.Email, l.svcCtx.Config.Ldap.PeopleGroupDN) + //查询dn + ldapServer := ldap_lib.NewLdap(l.svcCtx.Ldap, l.svcCtx.Config.Ldap.BaseDN, l.svcCtx.Config.Ldap.RootDN, l.svcCtx.Config.Ldap.PeopleGroupDN) + ldapUserInfo, err := ldapServer.GetLdapUserInfo(userDN) + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeServiceErr, "获取用户信息失败,"+err.Error()) + } + if ldapUserInfo.Status != 1 { + return resp.SetStatusWithMessage(basic.CodeUnAuth, "无权限登录") + } + if len(ldapUserInfo.Password) <= 7 { + return resp.SetStatusWithMessage(basic.CodeUnAuth, "该帐号密码异常") + } + //解密密码 + ldapPwd, err := encryption_decryption.CBCDecrypt(ldapUserInfo.Password[7:]) + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeServiceErr, "验证密码出错了!") + } + //比较密码 + if ldapPwd != req.Password { + return resp.SetStatusWithMessage(basic.CodeServiceErr, "密码错误!") + } + //生成token + token, err := ldapServer.GenJwtToken(ldapUserInfo.UserId, 36000, ldapUserInfo.UserDN, ldapUserInfo.Password) + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeServiceErr, "生成登录凭证失败") + } + return resp.SetStatusWithMessage(basic.CodeOK, "success", types.LdapUserLoginRsp{ + Token: token, + }) +} + +// 处理逻辑后 w,r 如:重定向, resp 必须重新处理 +// func (l *LdapUserLoginLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) { +// // httpx.OkJsonCtx(r.Context(), w, resp) +// } diff --git a/server/ldap-admin/internal/types/types.go b/server/ldap-admin/internal/types/types.go index bd1cf72b..3b0b706b 100644 --- a/server/ldap-admin/internal/types/types.go +++ b/server/ldap-admin/internal/types/types.go @@ -225,6 +225,15 @@ type GetLdapUsersItem struct { Status int64 `json:"status,options=0|1"` //状态 1正常0离职 } +type LdapUserLoginReq struct { + Email string `json:"email"` + Password string `json:"password"` +} + +type LdapUserLoginRsp struct { + Token string `json:"token"` +} + type Request struct { } diff --git a/server_api/ldap-admin.api b/server_api/ldap-admin.api index ef2b9653..fc17bfa4 100644 --- a/server_api/ldap-admin.api +++ b/server_api/ldap-admin.api @@ -92,6 +92,9 @@ service ldap-admin { //获取基础用户组中成员列表 @handler GetLdapUsersHandler get /api/ldap-admin/get_ldap_users(GetLdapUsersReq) returns (response); + //登录 + @handler LdapUserLoginHandler + post /api/ldap-admin/ldap_user_login(LdapUserLoginReq) returns (response); } type ( @@ -302,4 +305,12 @@ type GetLdapUsersItem { Avatar string `json:"avatar"` //头像地址 EmployeeType int64 `json:"employee_type"` Status int64 `json:"status,options=0|1"` //状态 1正常0离职 +} +//登录 +type LdapUserLoginReq { + Email string `json:"email"` + Password string `json:"password"` +} +type LdapUserLoginRsp { + Token string `json:"token"` } \ No newline at end of file diff --git a/utils/ldap_lib/jwt_parse.go b/utils/ldap_lib/jwt_parse.go new file mode 100644 index 00000000..6dcaa432 --- /dev/null +++ b/utils/ldap_lib/jwt_parse.go @@ -0,0 +1,51 @@ +package ldap_lib + +import ( + "encoding/json" + "errors" + "github.com/golang-jwt/jwt" + "time" +) + +type UserInfo struct { + UserDN string `json:"user_dn"` + UserId int64 `json:"user_id"` +} + +// 生成token +func (l *Ldap) GenJwtToken(userId, expireTime int64, userDN, password string) (token string, err error) { + t := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "user_dn": userDN, + "user_id": userId, + "exp": time.Now().Add(time.Second * time.Duration(expireTime)).Unix(), //过期时间 + "iss": "fusen", + }) + token, err = t.SignedString([]byte(password)) + if err != nil { + return "", err + } + return "Bearer " + token, nil +} + +// 解释token +func (l *Ldap) ParseJwtToken(token, password string) (UserInfo, error) { + if len(token) <= 7 || token[:7] != "Bearer " { + return UserInfo{}, errors.New("无效的token") + } + token = token[7:] + t, err := jwt.ParseWithClaims(token, jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) { + return []byte(password), nil + }) + if err != nil { + return UserInfo{}, err + } + d, err := json.Marshal(t.Claims) + if err != nil { + return UserInfo{}, err + } + var userInfo UserInfo + if err = json.Unmarshal(d, &userInfo); err != nil { + return UserInfo{}, err + } + return userInfo, nil +}