钉钉实现扫码登录
实现背景
我们小组用的是钉钉办公,所以我们开发一些网站都是服务于小组内成员,也就是企业内部钉钉用户,在之前已经实现了将钉钉用户信息同步在数据库中,所以我们直接根据钉钉开发文档实现第三方登录。
具体思路
1.数据库已经同步到企业内部所有成员的信息,等于说所有用户都已经注册过了
2.实现扫码登录,通过用户钉钉登录或钉钉扫码登录获取用户信息,然后根据获取的信息在数据库中验证身份,得到完整信息,并生成该用户登录的token,并将用户信息存入token请求头,实现完整登录过程。
参考文档和在线接口测试
第三方登录文档
获取用户token
企业内部api在线测试上面这个接口
获取通讯录个人信息
企业内部api在线测试上面这个接口
具体演示过程
1.根据钉钉官方给定的网址(网址中包含你最后要跳转到的你的项目地址)进入,让用户授权
我的网址:
https://login.dingtalk.com/oauth2/challenge.htm?redirect_uri=http://47.98.212.252/&response_type=code&client_id=dingjfxu75nqiffmdbb8&scope=openid&prompt=consent

2.登录之后网址上会获取authCode=2091bc1e2d8630ae84bf06844721c5d4,这个码只能用一次,具有即时性,也有过期时间
当你还没有写后端逻辑,没有验证获取token的时候,他默认跳转到你给定的登录页面

3.前端获取这个码传给后端,然后你根据你写的接口,返回给前端这个用户的所有信息和token
也就是直接进入展示页面,而不是登录页面
实现代码
type Code struct {AuthCode string `json:"authCode"`
}
func SweepLogin(code *models.Code) (list models.UserList, err error) {accessToken, err := GetAccessToken(code)var client *http.Clientvar request *http.Requestvar resp *http.Responsevar body []byteURL := "https://api.dingtalk.com/v1.0/contact/users/me"client = &http.Client{Transport: &http.Transport{ //对客户端进行一些配置TLSClientConfig: &tls.Config{InsecureSkipVerify: true,},}, Timeout: time.Duration(time.Second * 5)}request, err = http.NewRequest("GET", URL, nil)if err != nil {return}// Set the header parameterrequest.Header.Set("x-acs-dingtalk-access-token", accessToken)request.Header.Set("Content-Type", "application/json")// Send the requestresp, err = client.Do(request)if err != nil {// Handle error}defer resp.Body.Close()// Read the response bodybody, err = ioutil.ReadAll(resp.Body)if err != nil {// Handle error}r := struct {AvatarURL string `json:"avatarUrl"`Mobile string `json:"mobile"`Nick string `json:"nick"`OpenID string `json:"openId"`StateCode string `json:"stateCode"`UnionID string `json:"unionId"`}{}//把请求到的结构反序列化到专门接受返回值的对象上面err = json.Unmarshal(body, &r)if err != nil {return}u := db.Table("user_lists").Where("unionid = ?", r.UnionID).Find(&user)if u.RowsAffected == 0 {// 用户不存在return list, ErrorUserNotExit}db.Table("user_lists").Where("unionid = ?", r.UnionID).Find(&list)return list, err
}func GetAccessToken(code *models.Code) (accessToken string, err error) {var client *http.Clientvar request *http.Requestvar resp *http.Responsevar body []byteURL := "https://api.dingtalk.com/v1.0/oauth2/userAccessToken"client = &http.Client{Transport: &http.Transport{ //对客户端进行一些配置TLSClientConfig: &tls.Config{InsecureSkipVerify: true,},}, Timeout: time.Duration(time.Second * 5)}//此处是post请求的请求题,我们先初始化一个对象b := struct {ClientID string `json:"clientId"`ClientSecret string `json:"clientSecret"`Code string `json:"code"`GrantType string `json:"grantType"`}{ClientID: "dingjfxu75nqiffmdbb8",ClientSecret: "X-ZVvfCTSl8qPWZEBI2VzJVQnkHoiikZ90gceJnZpIzhDGw5a3wFpXcy6Ce85c1x",Code: code.AuthCode,GrantType: "authorization_code",}//然后把结构体对象序列化一下bodymarshal, err := json.Marshal(&b)if err != nil {return}//再处理一下reqBody := strings.NewReader(string(bodymarshal))//然后就可以放入具体的request中的request, err = http.NewRequest(http.MethodPost, URL, reqBody)if err != nil {return}request.Header.Set("Content-Type", "application/json")resp, err = client.Do(request)if err != nil {return}defer resp.Body.Close()body, err = ioutil.ReadAll(resp.Body) //把请求到的body转化成byte[]if err != nil {return}r := struct {AccessToken string `json:"accessToken"`Code string `json:"code"`ExpireIn int64 `json:"expireIn"`Message string `json:"message"`RefreshToken string `json:"refreshToken"`Requestid string `json:"requestid"`}{}//把请求到的结构反序列化到专门接受返回值的对象上面err = json.Unmarshal(body, &r)if err != nil {return}if r.Code != "" {return "", errors.New(r.Message)}return r.AccessToken, nil
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
