钉钉免登显示钉钉用户名和头像,配置XSRF,修复一些BUG

pull/665/head
LawyZHENG 2021-03-25 10:04:15 +08:00
parent 350bdc4d02
commit 9141487aa3
7 changed files with 79 additions and 15 deletions

View File

@ -7,6 +7,7 @@ runmode = "${MINDOC_RUN_MODE||dev}"
sessionon = true sessionon = true
sessionname = mindoc_id sessionname = mindoc_id
copyrequestbody = true copyrequestbody = true
enablexsrf = true
#系统完整URL(http://doc.iminho.me),如果该项不设置,会从请求头中获取地址。 #系统完整URL(http://doc.iminho.me),如果该项不设置,会从请求头中获取地址。
baseurl="${MINDOC_BASE_URL}" baseurl="${MINDOC_BASE_URL}"
@ -209,6 +210,20 @@ log_level="${MINDOC_LOG_LEVEL||Alert}"
# 是否异步生成日志,默认是 true # 是否异步生成日志,默认是 true
log_is_async="${MINDOC_LOG_IS_ASYNC||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}"

View File

@ -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 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-Z][a-zA-Z0-9\.-]{2,50}$`
const RegexpAccount = `[a-zA-Z0-9\.-]{2,50}$`
// PageSize 默认分页条数. // PageSize 默认分页条数.
const PageSize = 10 const PageSize = 10

View File

@ -32,9 +32,12 @@ func (c *AccountController) referer() string {
func (c *AccountController) Prepare() { func (c *AccountController) Prepare() {
c.BaseController.Prepare() c.BaseController.Prepare()
c.EnableXSRF = true c.EnableXSRF = beego.AppConfig.DefaultBool("enablexsrf", true)
c.Data["xsrfdata"] = template.HTML(c.XSRFFormHTML()) c.Data["xsrfdata"] = template.HTML(c.XSRFFormHTML())
c.Data["corpID"] = beego.AppConfig.String("dingtalk_corpid") c.Data["corpID"] = beego.AppConfig.String("dingtalk_corpid")
if !c.EnableXSRF {
return
}
if c.Ctx.Input.IsPost() { if c.Ctx.Input.IsPost() {
token := c.Ctx.Input.Query("_xsrf") token := c.Ctx.Input.Query("_xsrf")
if token == "" { if token == "" {
@ -138,7 +141,7 @@ func (c *AccountController) Login() {
func (c *AccountController) DingTalkLogin() { func (c *AccountController) DingTalkLogin() {
c.Prepare() c.Prepare()
code := c.GetString("code") code := c.GetString("dingtalk_code")
if code == "" { if code == "" {
c.JsonResult(500, "获取身份信息失败", nil) c.JsonResult(500, "获取身份信息失败", nil)
} }
@ -160,7 +163,14 @@ func (c *AccountController) DingTalkLogin() {
c.StopRun() 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 { if err != nil {
beego.Warn("钉钉自动登录失败 ->", err) beego.Warn("钉钉自动登录失败 ->", err)
c.JsonResult(500, "自动登录失败", nil) c.JsonResult(500, "自动登录失败", nil)
@ -171,6 +181,10 @@ func (c *AccountController) DingTalkLogin() {
if err == nil { if err == nil {
member.LastLoginTime = time.Now() member.LastLoginTime = time.Now()
_ = member.Update("last_login_time") _ = member.Update("last_login_time")
member.Account = username
if avatar != "" {
member.Avatar = avatar
}
c.SetMember(*member) c.SetMember(*member)
} }

View File

@ -179,10 +179,6 @@ func (m *Member) httpLogin(account, password string) (*Member, error) {
return nil, ErrMemberAuthMethodInvalid return nil, ErrMemberAuthMethodInvalid
} }
tmpH := md5.New()
tmpH.Write([]byte(password))
password = strings.ToUpper(hex.EncodeToString(tmpH.Sum(nil)))
val := url.Values{ val := url.Values{
"account": []string{account}, "account": []string{account},
"password": []string{password}, "password": []string{password},

View File

@ -227,7 +227,7 @@ limit ?;`
for _, member := range members { for _, member := range members {
item := KeyValueItem{} item := KeyValueItem{}
item.Id = member.MemberId item.Id = member.MemberId
item.Text = member.Account + "(" + member.RealName + ")" item.Text = member.Account + "[" + member.RealName + "]"
items = append(items, item) items = append(items, item)
} }
result.Result = items result.Result = items

View File

@ -27,8 +27,8 @@ func NewDingTalkAgent(appSecret, appKey string) *DingTalkAgent {
} }
} }
// GetUserNameByCode 通过临时code获取当前用户信息 // GetUserIDByCode 通过临时code获取当前用户ID
func (d *DingTalkAgent) GetUserNameByCode(code string) (string, error) { func (d *DingTalkAgent) GetUserIDByCode(code string) (string, error) {
urlEndpoint, err := url.Parse("https://oapi.dingtalk.com/user/getuserinfo") urlEndpoint, err := url.Parse("https://oapi.dingtalk.com/user/getuserinfo")
if err != nil { if err != nil {
return "", err 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))) return "", errors.New(fmt.Sprintf("登录错误: %.0f, %s", errcode, rdata["errmsg"].(string)))
} }
username := rdata["name"].(string) userid := rdata["userid"].(string)
return username, nil 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 // GetAccesstoken 获取钉钉请求Token

View File

@ -99,7 +99,7 @@
}) })
var formData = $("form").serializeArray() var formData = $("form").serializeArray()
formData.push({"name": "code", "value": info.code}) formData.push({"name": "dingtalk_code", "value": info.code})
$.ajax({ $.ajax({
url: "{{urlfor "AccountController.DingTalkLogin"}} ", url: "{{urlfor "AccountController.DingTalkLogin"}} ",