钉钉客户端JS-API权限签名算法.NET版
前段时间写了一篇博文《钉钉如何进行PC端开发》,在里面并未解决本地生成签名的问题,需要到官网进行生成,由于钉钉门票等认证信息会超期,因此,必须能本地用代码自动更新相关参数信息,来换取签名。官方文档由于这块并未有.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=http://open.dingtalk.com
步骤1. sort()含义为对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)
步骤2. assemble()含义为根据步骤1中获的参数字段的顺序,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串
步骤2. sha1()的含义为对在步骤2拼接好的字符串进行sha1加密。(PS:明明是步骤3好么!)
一开始没有理解,用代码生成签名和官方的就是对不上,很是打击。但是后来发现就是没有理解文档中的第一步,后来发现是:签名参数按照【字段名】而非一开始理解的参数值。
既然理解了,那么先看看签名参数按照字段名noncestr、jsapi_ticket、timestamp和url的字典排序吧:
ArrayList AL = new ArrayList();
AL.Add("noncestr");
AL.Add("jsapi_ticket");
AL.Add("timestamp");
AL.Add("url");
AL.Sort();

那么下一步就是拼接字符串了:
string assemble =string.Format("jsapi_ticket={0}&noncestr={1}×tamp={2}&url={3}", jsapi_ticket, noncestr,sTimeStamp, url);
最后一步骤:
sha = new SHA1CryptoServiceProvider();
enc = new ASCIIEncoding();
byte[] dataToHash = enc.GetBytes(assemble);
byte[] dataHashed = sha.ComputeHash(dataToHash);
hash = BitConverter.ToString(dataHashed).Replace("-", "");
hash = hash.ToLower();
完整代码如下,注意此包含时间戳的生产方法:
using System;
using System.Text;
using System.Security.Cryptography;
using Suite.Corp;
using System.Collections;
/*
* Author:JackWangCUMT
* Date:2016-04-26 8:36
* Blogs:http://www.cnblogs.com/isaboy
* GitHub:https://github.com/JackWangCUMT
* QQ:308106637
*/
namespace myDDDev
{
public static class DingTalkAuth
{
/// <summary>
///开发者在web页面使用钉钉容器提供的jsapi时,需要验证调用权限,并以参数signature标识合法性
///签名生成的规则:
///List keyArray = sort(noncestr, timestamp, jsapi_ticket, url);
/// String str = assemble(keyArray);
///signature = sha1(str);
/// </summary>
/// <param name="noncestr">随机字符串,自己随便填写即可</param>
/// <param name="sTimeStamp">当前时间戳,具体值为当前时间到1970年1月1号的秒数</param>
/// <param name="jsapi_ticket">获取的jsapi_ticket</param>
/// <param name="url">当前网页的URL,不包含#及其后面部分</param>
/// <param name="signature">生成的签名</param>
/// <returns>0 成功,2 失败</returns>
public static int GenSigurate(string noncestr, string sTimeStamp, string jsapi_ticket, string url, ref string signature)
{ //例如:
//noncestr = Zn4zmLFKD0wzilzM
//jsapi_ticket = mS5k98fdkdgDKxkXGEs8LORVREiweeWETE40P37wkidkfksDSKDJFD5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcKIDU8l
//timestamp = 1414588745
//url = http://open.dingtalk.com //步骤1.sort()含义为对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)
//注意,此处是是按照【字段名】的ASCII字典序,而不是参数值的字典序(这个细节折磨我很久了)
//0:jsapi_ticket 1:noncestr 2:timestamp 3:url; //步骤2.assemble()含义为根据步骤1中获的参数字段的顺序,使用URL键值对的格式(即key1 = value1 & key2 = value2…)拼接成字符串
//string assemble = "jsapi_ticket=3fOo5UfWhmvRKnRGMmm6cWwmIxDMCnniyVYL2fqcz1I4GNU4054IOlif0dZjDaXUScEjoOnJWOVrdwTCkYrwSl&noncestr=CUMT1987wlrrlw×tamp=1461565921&url=https://jackwangcumt.github.io/home.html";
string assemble =string.Format("jsapi_ticket={0}&noncestr={1}×tamp={2}&url={3}", jsapi_ticket, noncestr,sTimeStamp, url);
//步骤2.sha1()的含义为对在步骤2拼接好的字符串进行sha1加密。
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 ;
}
signature = hash;
return ; } /// <summary>
/// 获取时间戳timestamp(当前时间戳,具体值为当前时间到1970年1月1号的秒数)
/// </summary>
/// <returns></returns>
public static string GetTimeStamp()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(, , , , , , );
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 = ;
while (index < iLeftLength && index < iRightLength)
{
if (sLeft[index] < sRight[index])
return -;
else if (sLeft[index] > sRight[index])
return ;
else
index++;
}
return iLeftLength - iRightLength; }
}
}
}
代码已经放置在GitHub上:https://github.com/JackWangCUMT/DDHelper
钉钉客户端JS-API权限签名算法.NET版的更多相关文章
- js api 实现钉钉免登
js api 实现钉钉免登,用于从钉钉微应用跳转到企业内部的oa,erp等,我刚刚实施完了我公司的这个功能,钉钉用起来还不错. 1 js api 实现钉钉免登,页面配置. <title>利 ...
- 钉钉服务端api接口使用
原文链接:http://www.cnblogs.com/xiaosongJiang/p/9991573.html 第一步:注册钉钉企业账号 打开链接:https://oa.dingtalk.com/# ...
- 钉钉js依赖库学习
看别人用的依赖库的好处在于,你知道有什么可以用,什么可以借鉴.(钉钉——协作桌面应用) PS:人最怕是不知道,而不是你不会. 1. jQuery 钉钉使用了1.9.1版本的jQuery,jQuery作 ...
- 微信客户端自带的Js Api:WeixinJSBridge
<!DOCTYPE html> <html> <head> <title>微信WeixinJSBridge API</title> < ...
- 通过钉钉网页上的js学习xss打cookie
做完了一个项目,然后没啥事做,无意看到了一个钉钉的外部链接: 题外话1: 查看源码,复制其中的代码: try { var search = location.search; if (search &a ...
- 这个API Hub厉害了,收录了钉钉企业微信等开放Api,还能直接调试
01 此前时不时会有一些研发小伙伴和我诉苦,说很多企业由于人力财力限制或者需求不强,会直接购买使用第三方的开放API,这样一来, 一则由于开放项目不是量身定制的,寻找自己合适的接口也要搜索调研蛮多时间 ...
- ASP.NET C# 实现钉钉签名算法
在 https://open-doc.dingtalk.com/microapp/faquestions/hxs5v9 钉钉给出了JAVA/PHP算法,下面是C#算法 using System.Sec ...
- 钉钉如何进行PC端开发
前段时间,用钉钉进行了服务器端的开发,对照着官方文档,感觉还是比较顺利的.后续想有时间研究一下PC端客户端的开发,看着官方文档,说的确实是比较简练,但也确实没看太明白,废了半天劲也没成功.后来经过无数 ...
- Java钉钉开发_02_免登授权(身份验证)(附源码)
源码已上传GitHub: https://github.com/shirayner/DingTalk_Demo 一.本节要点 1.免登授权的流程 (1)签名校验 (2)获取code,并传到后台 (3) ...
随机推荐
- Account problem-There may be a problem with your account. Please contact us. Sign out
很多人在使用开发者账号AppleID的时候,都会碰到如下问题 There may be a problem with your account. Please contact us. 登录到苹果的开发 ...
- 关于Git和Github你不知道的十件事
Git 和 GitHub都是非常强大的工具.即使你已经使用他们很长时间,你也很有可能不知道每个细节.我整理了Git和GitHub可能提高日常效率的10个常用技巧. GitHub 快捷键: t 和 w ...
- 深入理解PHP内核(十三)类的结构和实现
原文链接:http://www.orlion.ga/1117/ 先看一下类的结构: struct _zend_class_entry { char type; // 类型:ZEND_ ...
- javascript中数组的22种方法
× 目录 [1]对象继承 [2]数组转换 [3]栈和队列[4]数组排序[5]数组拼接[6]创建数组[7]数组删改[8]数组位置[9]数组归并[10]数组迭代[11]总结 前面的话 数组总共有22种方法 ...
- Greenplum测试环境部署
1.准备3台主机 本实例是部署实验环境,采用的是Citrix的虚拟化环境,分配了3台RHEL6.4的主机. |------|------| |Master|创建模板后,额外添加20G一块磁盘/dev/ ...
- PHP面向对象中的重要知识点(二)
1. __toString: 当对象被打印时,如果该类定义了该方法,则打印该方法的返回值,否则将按照PHP的缺省行为输出打印结果.该方法类似于Java中的toString(). <?php cl ...
- SharedPreferences 详解(多进程,存取数组解决方案)
一.SharedPreferences基本概念 文件保存路径:/data/data/<包名>/shared_prefs目录下目录下生成了一个SP.xml文件 SharedPreferenc ...
- C#--参数数组
- [前端]使用JQuery UI Layout Plug-in布局 - wolfy
引言 使用JQuery UI Layout Plug-in布局框架实现快速布局,用起来还是挺方便的,稍微研究了一下,就能上手,关于该布局框架的材料,网上也挺多的.在项目中也使用到了,不过那是前端的工作 ...
- 用C语言来分割字符串
#include <stdio.h> int main() { ] = {}; ] = {}; ] = {}; sscanf("1,2,3#3,4#4,5"," ...