ASP.netcore MVC钉钉H5微应用(二)鉴权

您所在的位置:网站首页 钉钉jsapi偶发签名失败errorcode9 ASP.netcore MVC钉钉H5微应用(二)鉴权

ASP.netcore MVC钉钉H5微应用(二)鉴权

2023-09-15 15:06| 来源: 网络整理| 查看: 265

官方文档:鉴权 由于官方文档没有C#的,所以自己弄了个C#的

需要注意的是,不是所有功能都需要鉴权,但是在需要鉴权的地方,一定要有

-第一步:获得access_token 我使用的是企业内部应用 具体代码:

public string GetAuthToken() { IDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken"); OapiGettokenRequest request = new OapiGettokenRequest(); //这里直接安装dingtalk .net core 版本的sdk会报错,可以将配置方法改成使用using //Microsoft.Extensions.Configuration;并在appseting.json中配置即可 request.Appkey = Configuration["AppParameter:Appkey"]; request.Appsecret = Configuration["AppParameter:Appsecret"]; request.SetHttpMethod("GET"); OapiGettokenResponse response = client.Execute(request); return response.AccessToken; }

代码里面的Configuration是注入进去的,为了读取写入配置文件的数据,即一些固定的数据,比如key,CorpId等等 代码:

private readonly IConfiguration Configuration; public MyTestService(IConfiguration Configuration) { this.Configuration = Configuration; }

-第二步,获取jsapi_ticket

企业内部应用和第三方企业应用获取jsapi_ticket后,当jsapi_ticket未过期时,再次调用get_jsapi_ticket接口获取到的jsapi_ticket和老的jsapi_ticket值相同,只是过期时间续期2小时。企业内部应用获取jsapi_ticket,一个appKey对应一个jsapi_ticket,所以在使用的时候需要将jsapi_ticket以appKey为维度进行缓存下来(设置缓存过期时间2小时),并不需要每次都通过接口拉取

代码:

public string GetTicket(string access_token) { IDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/get_jsapi_ticket"); OapiGetJsapiTicketRequest req = new OapiGetJsapiTicketRequest(); req.SetHttpMethod("GET"); OapiGetJsapiTicketResponse rsp = client.Execute(req, access_token); return rsp.Ticket; }

-第三步:获取签名参数

//获取当前时间的时间戳 public static string ConvertDateTimeToInt() { TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } //获取签名 /* * 生成签名的函数 * params: * ticket:签名数据 * nonceStr:签名用的随机字符串,从properties文件中读取 * timeStamp:生成签名用的时间戳 * url:当前请求的URL地址 */ public string GetSign(string ticket, string noncestr, string timeStamp, string url) { string plain = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "×tamp=" + timeStamp.ToString() + "&url=" + url; SHA256 sha; ASCIIEncoding enc; string hash = ""; try { sha = new SHA256CryptoServiceProvider(); enc = new ASCIIEncoding(); byte[] dataToHash = enc.GetBytes(plain); byte[] dataHashed = sha.ComputeHash(dataToHash); hash = BitConverter.ToString(dataHashed).Replace("-", ""); hash = hash.ToLower(); } catch (Exception) { return "错误"; } var signature = hash; return signature; }

-第四步:创建_config的计算函数

/* * 将所有需要传送到前端的参数进行打包,在前端会调用jsapi提供的dd.config接口进行签名的验证 *params: * request:在钉钉中点击微应用图标跳转的url地址 *return: * 将需要的参数打包好,按json格式打包 */ public string GetConfig() { string nonceStr = Configuration["AppParameter:NonceStr"]; //固定任意字符串 string agentId = Configuration["AppParameter:AgentId"]; //agentid参数 string timeStamp = ConvertDateTimeToInt(); //时间戳参数 string accessToken = null; //token参数 string ticket = null; //ticket参数 string signature = null; //签名参数 string corpId = Configuration["AppParameter:CorpId"]; //CorpId参数 string signedUrl = Configuration["AppParameter:Url"]; //页面网址 try { accessToken = GetAuthToken(); ticket = GetTicket(accessToken); signature = GetSign(ticket, nonceStr, timeStamp, signedUrl); } catch (Exception e) { Console.WriteLine(e.ToString()); } var informationJson = new { jsticket = ticket, signature = signature, nonceStr = nonceStr, timeStamp = timeStamp, corpId = corpId, agentId = agentId, }; return JsonSerializer.Serialize(informationJson); }

-第五步,在前端调用此方法得到_config,我使用的是ajax的方式进行前后端交互

var _config; $.ajax({ async: false, type: 'get', contentType: "", datatype: "", data: {}, //为_config配值 url: '/home/GetConfig2', success: function (ref) { _config = eval('(' + ref + ')');//去掉json格式外面的双引号 }, });

-第六步,前端进行鉴权 代码:

dd.config({ agentId: _config.agentId, // 必填,微应用ID corpId: _config.corpId,//必填,企业ID timeStamp: _config.timeStamp, // 必填,生成签名的时间戳 nonceStr: _config.nonceStr, // 必填,自定义固定字符串。 signature: _config.signature, // 必填,签名 type: 0, //选填。0表示微应用的jsapi,1表示服务窗的jsapi;不填默认为0。该参数从dingtalk.js的0.8.3版本开始支持 jsApiList: [ 'runtime.info', 'biz.contact.choose', 'device.notification.confirm', 'device.notification.alert', 'device.notification.prompt', 'biz.ding.post', 'biz.util.openLink', 'biz.cspace.saveFile', 'biz.cspace.preview', 'biz.cspace.chooseSpaceDir', 'biz.util.uploadAttachment' ] // 必填,需要使用的jsapi列表,注意:不要带dd。 }); dd.error(function (err) { alert('dd error: ' + JSON.stringify(err)); })//该方法必须带上,用来捕获鉴权出现的异常信息,否则不方便排查出现的问题

这里首先要保证,能够准确获取到code以及token。

假如前端报错(官方文档),也就是执行了onFail: function (err) {}方法,报错信息如下:访问IP不在白名单之中。

当请求开放平台服务端接口遇到“访问IP不在白名单”问题时,表示您的请求IP不在该应用出口IP白名单内。

可以按照以下方式排查并修改:

(1)对比调用接口的应用中的AppKey值,与报错信息中返回的AppKey值是否一致。如果不一致,可能是由于AppKey或者AppSecret使用的是其他的,导致在获取AccessToken值时会提示错误。

注意:如果错误信息中返回的是CorpId值,说明创建应用时间较早,添加IP的路径为:登录开发者后台-基本信息-开发信息旧版-找到该应用使用的CorpSecret值,点击设置修改IP;如果当前账号按照上述路径查看不到CorpSecret,需要该企业主管理员账号查看并修改IP。

(2)如果应用中的AppKey值跟报错信息中返回的AppKey值是一致的,解决办法是将报错信息中的request IP添加到该应用的出口IP里面。

这个问题经常出现在当你用手机调试,并且你的笔记本连接手机WiFi时,就会出现这样的问题。

自此,鉴权结束



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3