From 9141487aa36609d30abbb88ff4d2d9760bf23eaf Mon Sep 17 00:00:00 2001 From: LawyZHENG Date: Thu, 25 Mar 2021 10:04:15 +0800 Subject: [PATCH] =?UTF-8?q?=E9=92=89=E9=92=89=E5=85=8D=E7=99=BB=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E9=92=89=E9=92=89=E7=94=A8=E6=88=B7=E5=90=8D=E5=92=8C?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=EF=BC=8C=E9=85=8D=E7=BD=AEXSRF=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=BA=9BBUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/app.conf.example | 15 ++++++++++ conf/enumerate.go | 3 +- controllers/AccountController.go | 20 +++++++++++-- models/Member.go | 4 --- models/TeamMember.go | 2 +- utils/dingtalk/dingtalk.go | 48 +++++++++++++++++++++++++++++--- views/account/login.tpl | 2 +- 7 files changed, 79 insertions(+), 15 deletions(-) diff --git a/conf/app.conf.example b/conf/app.conf.example index 1a4605a2..dffb9381 100644 --- a/conf/app.conf.example +++ b/conf/app.conf.example @@ -7,6 +7,7 @@ runmode = "${MINDOC_RUN_MODE||dev}" sessionon = true sessionname = mindoc_id copyrequestbody = true +enablexsrf = true #系统完整URL(http://doc.iminho.me),如果该项不设置,会从请求头中获取地址。 baseurl="${MINDOC_BASE_URL}" @@ -209,6 +210,20 @@ log_level="${MINDOC_LOG_LEVEL||Alert}" # 是否异步生成日志,默认是 true log_is_async="${MINDOC_LOG_IS_ASYNC||TRUE}" +##########钉钉应用相关配置############## + +# 企业钉钉ID +dingtalk_corpid="${MINDOC_DINGTALK_CORPID}" + +# 钉钉AppKey +dingtalk_app_key="${MINDOC_DINGTALK_APPKEY}" + +# 钉钉AppSecret +dingtalk_app_secret="${MINDOC_DINGTALK_APPSECRET}" + +# 钉钉登录默认只读账号 +dingtalk_tmp_reader="${MINDOC_DINGTALK_READER}" + diff --git a/conf/enumerate.go b/conf/enumerate.go index 89539ae9..ca97e039 100644 --- a/conf/enumerate.go +++ b/conf/enumerate.go @@ -20,8 +20,7 @@ const CaptchaSessionName = "__captcha__" const RegexpEmail = "^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" //允许用户名中出现点号 -// const RegexpAccount = `^[a-zA-Z][a-zA-Z0-9\.-]{2,50}$` -const RegexpAccount = `[a-zA-Z0-9\.-]{2,50}$` +const RegexpAccount = `^[a-zA-Z][a-zA-Z0-9\.-]{2,50}$` // PageSize 默认分页条数. const PageSize = 10 diff --git a/controllers/AccountController.go b/controllers/AccountController.go index 8998eb71..f5112dd9 100644 --- a/controllers/AccountController.go +++ b/controllers/AccountController.go @@ -32,9 +32,12 @@ func (c *AccountController) referer() string { func (c *AccountController) Prepare() { c.BaseController.Prepare() - c.EnableXSRF = true + c.EnableXSRF = beego.AppConfig.DefaultBool("enablexsrf", true) c.Data["xsrfdata"] = template.HTML(c.XSRFFormHTML()) c.Data["corpID"] = beego.AppConfig.String("dingtalk_corpid") + if !c.EnableXSRF { + return + } if c.Ctx.Input.IsPost() { token := c.Ctx.Input.Query("_xsrf") if token == "" { @@ -138,7 +141,7 @@ func (c *AccountController) Login() { func (c *AccountController) DingTalkLogin() { c.Prepare() - code := c.GetString("code") + code := c.GetString("dingtalk_code") if code == "" { c.JsonResult(500, "获取身份信息失败", nil) } @@ -160,7 +163,14 @@ func (c *AccountController) DingTalkLogin() { c.StopRun() } - username, err := dingtalkAgent.GetUserNameByCode(code) + userid, err := dingtalkAgent.GetUserIDByCode(code) + if err != nil { + beego.Warn("钉钉自动登录失败 ->", err) + c.JsonResult(500, "自动登录失败", nil) + c.StopRun() + } + + username, avatar, err := dingtalkAgent.GetUserNameAndAvatarByUserID(userid) if err != nil { beego.Warn("钉钉自动登录失败 ->", err) c.JsonResult(500, "自动登录失败", nil) @@ -171,6 +181,10 @@ func (c *AccountController) DingTalkLogin() { if err == nil { member.LastLoginTime = time.Now() _ = member.Update("last_login_time") + member.Account = username + if avatar != "" { + member.Avatar = avatar + } c.SetMember(*member) } diff --git a/models/Member.go b/models/Member.go index 1bbc7283..cf08c923 100644 --- a/models/Member.go +++ b/models/Member.go @@ -179,10 +179,6 @@ func (m *Member) httpLogin(account, password string) (*Member, error) { return nil, ErrMemberAuthMethodInvalid } - tmpH := md5.New() - tmpH.Write([]byte(password)) - password = strings.ToUpper(hex.EncodeToString(tmpH.Sum(nil))) - val := url.Values{ "account": []string{account}, "password": []string{password}, diff --git a/models/TeamMember.go b/models/TeamMember.go index 52ad32d5..f6f08b95 100644 --- a/models/TeamMember.go +++ b/models/TeamMember.go @@ -227,7 +227,7 @@ limit ?;` for _, member := range members { item := KeyValueItem{} item.Id = member.MemberId - item.Text = member.Account + "(" + member.RealName + ")" + item.Text = member.Account + "[" + member.RealName + "]" items = append(items, item) } result.Result = items diff --git a/utils/dingtalk/dingtalk.go b/utils/dingtalk/dingtalk.go index b4631dee..53954abe 100644 --- a/utils/dingtalk/dingtalk.go +++ b/utils/dingtalk/dingtalk.go @@ -27,8 +27,8 @@ func NewDingTalkAgent(appSecret, appKey string) *DingTalkAgent { } } -// GetUserNameByCode 通过临时code获取当前用户信息 -func (d *DingTalkAgent) GetUserNameByCode(code string) (string, error) { +// GetUserIDByCode 通过临时code获取当前用户ID +func (d *DingTalkAgent) GetUserIDByCode(code string) (string, error) { urlEndpoint, err := url.Parse("https://oapi.dingtalk.com/user/getuserinfo") if err != nil { return "", err @@ -62,8 +62,48 @@ func (d *DingTalkAgent) GetUserNameByCode(code string) (string, error) { return "", errors.New(fmt.Sprintf("登录错误: %.0f, %s", errcode, rdata["errmsg"].(string))) } - username := rdata["name"].(string) - return username, nil + userid := rdata["userid"].(string) + return userid, nil +} + +// GetUserNameAndAvatarByUserID 通过userid获取当前用户姓名和头像 +func (d *DingTalkAgent) GetUserNameAndAvatarByUserID(userid string) (string, string, error) { + urlEndpoint, err := url.Parse("https://oapi.dingtalk.com/topapi/v2/user/get") + if err != nil { + return "", "", err + } + + query := url.Values{} + query.Set("access_token", d.AccessToken) + + urlEndpoint.RawQuery = query.Encode() + urlPath := urlEndpoint.String() + + resp, err := http.PostForm(urlPath, url.Values{"userid": {userid}}) + if err != nil { + return "", "", err + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", "", err + } + + // 解析钉钉返回数据 + var rdata map[string]interface{} + err = json.Unmarshal(body, &rdata) + if err != nil { + return "", "", err + } + + errcode := rdata["errcode"].(float64) + if errcode != 0 { + return "", "", errors.New(fmt.Sprintf("登录错误: %.0f, %s", errcode, rdata["errmsg"].(string))) + } + + userinfo := rdata["result"].(map[string]interface{}) + username := userinfo["name"].(string) + avatar := userinfo["avatar"].(string) + return username, avatar, nil } // GetAccesstoken 获取钉钉请求Token diff --git a/views/account/login.tpl b/views/account/login.tpl index 92edba40..04efc2a8 100644 --- a/views/account/login.tpl +++ b/views/account/login.tpl @@ -99,7 +99,7 @@ }) var formData = $("form").serializeArray() - formData.push({"name": "code", "value": info.code}) + formData.push({"name": "dingtalk_code", "value": info.code}) $.ajax({ url: "{{urlfor "AccountController.DingTalkLogin"}} ",