钉钉客户端JS-API权限签名算法.NET版

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

钉钉客户端JS-API权限签名算法.NET版
前段时间写了⼀篇博⽂《》,在⾥⾯并未解决本地⽣成签名的问题,需要到官⽹进⾏⽣成,由于钉钉门票等认证信息会超期,因此,必须能本地⽤代码⾃动更新相关参数信息,来换取签名。

官⽅⽂
档由于这块并未有.NET版本的签名API可供调⽤,⽆奈只能⾃⼰摸索着进⾏实现。

可笑的是,在看钉钉⽂档时候并未理解其算法,但是却在看微信JS-API签名⽣成算法的时候顿悟了。

感觉⼆者这个权限
体系认证很是类似。

话不多说,切⼊正题。

钉钉⼴泛⽂档对于JS-API的说明是这样的:
开发者在web页⾯使⽤钉钉容器提供的jsapi时,需要验证调⽤权限,并以参数signature标识合法性
签名⽣成的规则:
List keyArray = sort(noncestr,timestamp,jsapi_ticket,url);
String str = assemble(keyArray);
signature = sha1(str);
参与签名的字段包括在上⽂中获取的jsapi_ticket,noncestr(随机字符串,⾃⼰随便填写即可),timestamp(当前时间戳,具体值为当前时间到1970年1⽉1号的秒数),url(当前⽹页的
URL,不包含#及其后⾯部分)。

例如:
noncestr=Zn4zmLFKD0wzilzM
jsapi_ticket=mS5k98fdkdgDKxkXGEs8LORVREiweeWETE40P37wkidkfksDSKDJFD5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcKIDU8l
timestamp=1414588745
url=
步骤1. sort()含义为对所有待签名参数按照字段名的ASCII 码从⼩到⼤排序(字典序)
步骤2. assemble()含义为根据步骤1中获的参数字段的顺序,使⽤URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串
步骤2. sha1()的含义为对在步骤2拼接好的字符串进⾏sha1加密。

(PS:明明是步骤3好么!)
⼀开始没有理解,⽤代码⽣成签名和官⽅的就是对不上,很是打击。

但是后来发现就是没有理解⽂档中的第⼀步,后来发现是:签名参数按照【字段名】⽽⾮⼀开始理解的参数值。

既然理解了,那么先看看签名参数按照字段名noncestr、jsapi_ticket、timestamp和url的字典排序吧:
1 ArrayList AL = new ArrayList();
2 AL.Add("noncestr");
3 AL.Add("jsapi_ticket");
4 AL.Add("timestamp");
5 AL.Add("url");
6 AL.Sort();
那么下⼀步就是拼接字符串了:
string assemble =string.Format("jsapi_ticket={0}&noncestr={1}&timestamp={2}&url={3}", jsapi_ticket, noncestr,sTimeStamp, url);
最后⼀步骤:
1 sha = new SHA1CryptoServiceProvider();
2 enc = new ASCIIEncoding();
3byte[] dataToHash = enc.GetBytes(assemble);
4byte[] dataHashed = puteHash(dataToHash);
5 hash = BitConverter.ToString(dataHashed).Replace("-", "");
6 hash = hash.ToLower();
完整代码如下,注意此包含时间戳的⽣产⽅法:
1using System;
2using System.Text;
3using System.Security.Cryptography;
4using Suite.Corp;
5using System.Collections;
6/*
7* Author:JackWangCUMT
8* Date:2016-04-26 8:36
9* Blogs:/isaboy
10* GitHub:https:///JackWangCUMT
11* QQ:308106637
12*/
13namespace myDDDev
14 {
15public static class DingTalkAuth
16 {
17///<summary>
18///开发者在web页⾯使⽤钉钉容器提供的jsapi时,需要验证调⽤权限,并以参数signature标识合法性
19///签名⽣成的规则:
20///List keyArray = sort(noncestr, timestamp, jsapi_ticket, url);
21/// String str = assemble(keyArray);
22///signature = sha1(str);
23///</summary>
24///<param name="noncestr">随机字符串,⾃⼰随便填写即可</param>
25///<param name="sTimeStamp">当前时间戳,具体值为当前时间到1970年1⽉1号的秒数</param>
26///<param name="jsapi_ticket">获取的jsapi_ticket</param>
27///<param name="url">当前⽹页的URL,不包含#及其后⾯部分</param>
28///<param name="signature">⽣成的签名</param>
29///<returns>0 成功,2 失败</returns>
30public static int GenSigurate(string noncestr, string sTimeStamp, string jsapi_ticket, string url, ref string signature)
31 {
32
33
34//例如:
35//noncestr = Zn4zmLFKD0wzilzM
36//jsapi_ticket = mS5k98fdkdgDKxkXGEs8LORVREiweeWETE40P37wkidkfksDSKDJFD5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcKIDU8l
37//timestamp = 1414588745
38//url =
39
40//步骤1.sort()含义为对所有待签名参数按照字段名的ASCII 码从⼩到⼤排序(字典序)
41//注意,此处是是按照【字段名】的ASCII字典序,⽽不是参数值的字典序(这个细节折磨我很久了)
42//0:jsapi_ticket 1:noncestr 2:timestamp 3:url;
43
44//步骤2.assemble()含义为根据步骤1中获的参数字段的顺序,使⽤URL键值对的格式(即key1 = value1 & key2 = value2…)拼接成字符串
45//string assemble = "jsapi_ticket=3fOo5UfWhmvRKnRGMmm6cWwmIxDMCnniyVYL2fqcz1I4GNU4054IOlif0dZjDaXUScEjoOnJWOVrdwTCkYrwSl&noncestr=CUMT1987wlrrlw&timestamp=1461565921&url= 46string assemble =string.Format("jsapi_ticket={0}&noncestr={1}&timestamp={2}&url={3}", jsapi_ticket, noncestr,sTimeStamp, url);
47//步骤2.sha1()的含义为对在步骤2拼接好的字符串进⾏sha1加密。

48 SHA1 sha;
49 ASCIIEncoding enc;
50string hash = "";
51try
52 {
53 sha = new SHA1CryptoServiceProvider();
54 enc = new ASCIIEncoding();
55byte[] dataToHash = enc.GetBytes(assemble);
56byte[] dataHashed = puteHash(dataToHash);
57 hash = BitConverter.ToString(dataHashed).Replace("-", "");
58 hash = hash.ToLower();
59 }
60catch (Exception)
61 {
62return2;
63 }
64 signature = hash;
65return0;
66
67 }
68
69///<summary>
70///获取时间戳timestamp(当前时间戳,具体值为当前时间到1970年1⽉1号的秒数) 71///</summary>
72///<returns></returns>
73public static string GetTimeStamp()
74 {
75 TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
76return Convert.ToInt64(ts.TotalSeconds).ToString();
77 }
78///<summary>
79///字典排序
80///</summary>
81public class DictionarySort : System.Collections.IComparer
82 {
83public int Compare(object oLeft, object oRight)
84 {
85string sLeft = oLeft as string;
86string sRight = oRight as string;
87int iLeftLength = sLeft.Length;
88int iRightLength = sRight.Length;
89int index = 0;
90while (index < iLeftLength && index < iRightLength)
91 {
92if (sLeft[index] < sRight[index])
93return -1;
94else if (sLeft[index] > sRight[index])
95return1;
96else
97 index++;
98 }
99return iLeftLength - iRightLength;
100
101 }
102 }
103 }
104 }
代码已经放置在GitHub上:https:///JackWangCUMT/DDHelper。

相关文档
最新文档