钉钉免登录

流程

首先需要理解一下钉钉的免登流程,借用官方文档的图片:

免登录步奏

  1. 已知Corpld和CropSecret,获取accessToken,即访问令牌。
  2. 通过accessToken,获取JsApiTicket,即JsApi的访问许可(门票)。
  3. 按照规则在后台由JsApiTicket、NonceStr、Timestamp、前端页面Url生成字符串,计算SHA1消息摘要,即签名Signature。
  4. 把AgentId、CorpId、Timestamp、NonceStr、Signature等参数传递到前台,在前台调用api,得到authCode,即授权码。
  5. 根据授权码,在前台或后台调用api,获得userId,进而再根据userId,调用api获取用户详细信息

主要代码

DingServerController

using Common;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApIs.BLL;
using WebApIs.Models;

namespace WebApIs.Controllers
{/// <summary>
/// 
/// </summary>
    public class DingServerController : ApiController
    {

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public ResultJson GetLoginSign()
        {
            string corpId = "dinga85d93", corpSecret = "D5r1G6cejOlZmEaB8PNlI9J5D";
            string nonceStr = new Random().Next(1000, 10000).ToString(); //"helloDD";//todo:随机
            string NonceStr = nonceStr;
            string AccessToken = GetAccessToken(corpId, corpSecret);
            string ticket = GetJsApiTicket(AccessToken);

            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            long timeStamp = Convert.ToInt64(ts.TotalSeconds);

            //?后端缺获取签名摘要
            string url = "http://10.10.10.10:8084/Index.html";//访问的页面 Request.Url.ToString();
            string signature = "";
            int sta = DDev.GetSign(ticket, nonceStr, timeStamp, url, ref signature);
            return new ResultJson { agentId = "207623633", corpId = corpId, timeStamp = timeStamp, nonceStr = NonceStr, signature = signature };


        }
        /// <summary>
        /// /
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
       // [HttpPost]
        public ResultJson GetCurrentUser(string code)
        {
            HROCPeopleBll ppbll = new HROCPeopleBll();
            string corpId = "dinga85d9", corpSecret = "D5r1G6cejOlZmEaB8PNlI9J5";
            string access_token = GetAccessToken(corpId, corpSecret);
            string tagUrl = "https://oapi.dingtalk.com/user/getuserinfo?access_token=" + access_token + "&code=" + code;
            string result = GetContents(tagUrl);
            var userModel = JsonConvert.DeserializeObject<UserInfo>(result);
            string ddid = userModel.userid;
            HROCPeople pp = new HROCPeople();
            pp = ppbll.GetPeopleModel(ddid);
            userModel.BpmLoginName = pp.LoginName;
            userModel.BpmUserID = pp.ID;
            userModel.BpmUserName = pp.Name;
            return new ResultJson { DetailData = userModel };
            //  var dtmodel= JsonConvert.DeserializeObject<HROCPeople>(dt);
            //return new ResultJson { DetailData= pp.Name,data=pp.LoginName };

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="DDID"></param>
        /// <returns></returns>
        public ResultJson GetCurrentUsers(string DDID)
        {
            HROCPeopleBll ppbll = new HROCPeopleBll();
            HROCPeople hrp = ppbll.GetPeopleModel(DDID);
            return new ResultJson { DetailData = hrp };
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="DDID"></param>
        /// <returns></returns>
        public string GetName(string DDID)
        {
            //return string.Format("姓名:{0}", Name);
            HROCPeopleBll ppbll = new HROCPeopleBll();
            HROCPeople hrp = ppbll.GetPeopleModel(DDID);
            return string.Format("姓名:{0},登录名:{1},ID:{2} ", hrp.Name, hrp.LoginName, hrp.ID);
            //return new ResultJson { data = hrp.Name, signature= hrp.LoginName };
        }
        //POST api/DingServer/GetCurrentUser? code = { code }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="corpId"></param>
        /// <param name="corpSecret"></param>
        /// <returns></returns>
        public string GetAccessToken(string corpId, string corpSecret)
        {
            string url = string.Format("https://oapi.dingtalk.com/gettoken?corpid={0}&corpsecret={1}", corpId, corpSecret);
            try
            {
                string response = GetContents(url);
                AccessTokenModel oat = Newtonsoft.Json.JsonConvert.DeserializeObject<AccessTokenModel>(response);
                if (oat != null)
                {
                    if (oat.errcode == 0)
                    {
                        return oat.access_token;
                    }
                }
            }
            catch (Exception ex)
            {
                throw;
            }
            return string.Empty;
        }

        public string GetJsApiTicket(string accessToken)
        {
            string url = string.Format("https://oapi.dingtalk.com/get_jsapi_ticket?access_token={0}", accessToken);
            try
            {
                string response = GetContents(url);
                JsApiTicketModel model = Newtonsoft.Json.JsonConvert.DeserializeObject<JsApiTicketModel>(response);

                if (model != null)
                {
                    if (model.errcode == 0)
                    {
                        return model.ticket;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return string.Empty;
        }
        public static string GetContents(string url)
        {
            WebRequest request = HttpWebRequest.Create(url);
            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader reader = new StreamReader(stream);
            string content = reader.ReadToEnd();
            return content;
        }


    }

    public class AccessTokenModel
    {
        public string access_token { get; set; }

        public int errcode { get; set; }

        public string errmsg { get; set; }
    }

    public class JsApiTicketModel
    {
        public string ticket { get; set; }

        public int errcode { get; set; }

        public string errmsg { get; set; }
    }

    public class UserIdModel
    {
        public string userid { get; set; }

        public int errcode { get; set; }

        public string errmsg { get; set; }
    }

    public class UserDetailInfo
    {
        public string userid { get; set; }

        public int errcode { get; set; }

        public string username { get; set; }
    }
}
View Code

HROCPeople

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebApIs.Models
{
    public class HROCPeople
    {
        public string ID { get; set; }
        public int IntID { get; set; }
        public string JobID { get; set; }
        public string CreateTime { get; set; }
        public string Name { get; set; }

        public string LoginName { get; set; }
        public string CompanyID { get; set; }
        public string DepartmentID { get; set; }
        //钉钉号 格式:{"DING":"211202322424329696"}
        public string other1 { get; set; }
    }
}
View Code

钉钉帮助类

using System;
using System.Text;
using System.Security.Cryptography;
using System.Collections;

namespace Common
{
    public static class DDev
    {
       
        public static int GenSigurate(string jsapi_ticket, string noncestr, string sTimeStamp, string url, ref string signature)
        {


           string assemble = string.Format("jsapi_ticket={0}&noncestr={1}&timestamp={2}&url={3}", jsapi_ticket, noncestr, sTimeStamp, url);
            SHA1 sha;
            ASCIIEncoding enc;
            string hash = "";
            try
            {
                sha = new SHA1CryptoServiceProvider();
                enc = new ASCIIEncoding();
                byte[] dataToHash = enc.GetBytes(assemble);
                byte[] dataHashed = sha.ComputeHash(dataToHash);
                hash = BitConverter.ToString(dataHashed).Replace("-", "");
                hash = hash.ToLower();
            }
            catch (Exception)
            {
                return 2;
            }
            signature = hash;
            return 0;

        }

        public static int GetSign(string ticket, string nonceStr, long timeStamp, string url, ref string signature)
        {
            String plain = string.Format("jsapi_ticket={0}&noncestr={1}&timestamp={2}&url={3}", ticket, nonceStr, timeStamp, url);
            try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(plain);
                byte[] digest = SHA1.Create().ComputeHash(bytes);
                string digestBytesString = BitConverter.ToString(digest).Replace("-", "");
                signature = digestBytesString.ToLower();
                return 1;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>
        /// 获取时间戳timestamp(当前时间戳,具体值为当前时间到1970年1月1号的秒数)
        /// </summary>
        /// <returns></returns>
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        /// <summary>
        /// 字典排序
        /// </summary>
        public class DictionarySort : System.Collections.IComparer
        {
            public int Compare(object oLeft, object oRight)
            {
                string sLeft = oLeft as string;
                string sRight = oRight as string;
                int iLeftLength = sLeft.Length;
                int iRightLength = sRight.Length;
                int index = 0;
                while (index < iLeftLength && index < iRightLength)
                {
                    if (sLeft[index] < sRight[index])
                        return -1;
                    else if (sLeft[index] > sRight[index])
                        return 1;
                    else
                        index++;
                }
                return iLeftLength - iRightLength;

            }
        }
    }
}
View Code

前端代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>钉钉服务接口调试</title>
    <!--<script type="text/javascript" src="script/jquery.min.js"></script>
    <script type="text/javascript" src="script/bootstrap.min.js"></script>-->
    <script src="//cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
    <script type="text/javascript" src="http://g.alicdn.com/dingding/open-develop/1.5.1/dingtalk.js"></script>
    <link type="text/css" rel="stylesheet" href="content/bootstrap.css" media="screen" />
    <style>
        body {
            margin: 20px 20px;
        }
    </style>
</head>
<body>


    <div class="panel panel-primary">

        <div class="panel-heading">
            <h3 class="panel-title">用户接口</h3>
        </div>
        <input id="notice" type="text" />
        <div class="panel-body">
            <div class="method-margin col-md-12">
                <div style="margin-bottom:5px;">
                    <button type="button" class="btn btn-default" data-loading-text="正在请求..." id="getUserDetail">获取用户详情</button>


                </div>
                <div class="method-output-padding">
                    <div class="logs-margin alert alert-danger alert-dismissible" role="alert" name="showErrorAlert">
                        <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
                        <span name="errorText"></span>
                    </div>
                    <div class="logs-margin alert alert-success alert-dismissible" role="alert" name="showInfoAlert">
                        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                            <span aria-hidden="true">×</span>
                        </button>
                        <span name="successText"></span>

                    </div>
                </div>
            </div>
        </div>
    </div>




    <script type="text/javascript">

        function login1(id) {
            $.ajax({
                url: 'http://10.10.10.10:8081/api/DingServer/GetName',
                type: 'get',
                //  dataType: 'JSON',
                data: { "DDID": id },
                success: function (data) {
                   // alert(JSON.stringify(data))
                    alert(data)
                    //var DDID = data.DetailData.userid;
                    //alert(DDID)
                    //login1(data.DetailData.userid)
                },
                error: function (data) {
                   // alert(JSON.stringify(data))
                }
            })
        }

        //function login1(id) {
        //    $.ajax({
        //        url: 'http://10.10.10.10:8081/api/DingServer/GetCurrentUsers',
        //        type: 'get',
        //        //  dataType: 'JSON',
        //        data: { DDID: id },
        //        success: function (data) {
        //            alert(data)
        //            //var DDID = data.DetailData.userid;
        //            //alert(DDID)
        //            //login1(data.DetailData.userid)
        //        },
        //        error: function (data) {
        //            alert(JSON.stringify(data))
        //        }
        //    })
        //}

        function login(code) {
            $.ajax({
                url: 'http://10.10.10.10:8081/api/DingServer/GetCurrentUser',
                type: 'GET',
              //  dataType: 'JSON',
                data: {code:code },
                success: function (data, status, xhr) {
                    //alert(JSON.stringify(data))
                    alert(data.DetailData.BpmUserID + "-" + data.DetailData.BpmUserName + "-" + data.DetailData.BpmLoginName)
                },
                error: function (data) {
                    alert(JSON.stringify(data))
                }
            })
        }

        //获取签名摘要??
        $(document).ready(function () {
            $.ajax({
                url: "http://10.10.10.10:8081/api/DingServer/GetLoginSign",
                type: 'GET',
                success: function (data, status, xhr) {
                     if (data.code != 0) {
                    } else {
                        var str = JSON.stringify(data);
                       // alert(str);
                        dd.config({
                            agentId: data.agentId,
                            corpId: data.corpId,
                            timeStamp: data.timeStamp,
                            nonceStr: data.nonceStr,
                            signature: data.signature,
                            jsApiList: ['runtime.info', 'biz.contact.choose',
                                    'device.notification.confirm', 'device.notification.alert',
                                    'device.notification.prompt', 'biz.ding.post',
                                    'biz.util.openLink']
                        });

                        dd.error(function (err) {
                            alert('dd error: ' + JSON.stringify(err))
                        })

                        dd.ready(function () {
                            dd.runtime.permission.requestAuthCode({
                                corpId: data.corpId,
                                onSuccess: function (result) {
                                    alert(JSON.stringify(result))
                                    login(result.code)
                                }
                            })
                        })


                    }
                },

                    error: function (data) {
                        console.log('err:', data)
                    }
            })

        })



    </script>
</body>
</html>
View Code

钉钉管理员配置应用

钉钉免登就是这样,只要弄懂了就会觉得其实不难。感谢阅读。

猜你喜欢

转载自www.cnblogs.com/Nlife/p/10087894.html