当前位置: 首页 > news >正文

wordpress 获取文章数量西安seo培训

wordpress 获取文章数量,西安seo培训,查询网站服务器地址,建一个自己的网站有什么用钉钉开发网页应用JSAPI前端授权鉴权nodejs实现 使用钉钉进行H5网页开发的时候,需要调用一些钉钉提供具有原生能力的api,要调用这些api需要进行jsapi授权。 详见官方文档(可选)开发网页应用前端 - 钉钉开放平台 (dingtalk.com) 官方…

钉钉开发网页应用JSAPI前端授权鉴权nodejs实现

使用钉钉进行H5网页开发的时候,需要调用一些钉钉提供具有原生能力的api,要调用这些api需要进行jsapi授权。
详见官方文档(可选)开发网页应用前端 - 钉钉开放平台 (dingtalk.com)
官方只提供了java和php的demo,并没有提供nodejs版本的后端权限方案,所以自己实现了一下

官方提供的步骤大致分为四个步骤(请务必阅读官方文档

  1. 获取token 我们将会实现token缓存,过期自动更新
  2. 获取jsapiTicket 我们将会实现ticket缓存,过期自动更新
  3. 计算签名 使用sha1包进行签名
  4. 使用官方sdk进行权限校验 前端调用sdk进行权限校验

我将代码分为两部分,一部分是前端,一部分是后端(nodejs)

前端实现,这里使用vue3演示

解释一下,下面的代码干了啥,当页面加载完成的时候,向后端http://192.168.1.63:3000/jsSdkAuthorized接口发送请求(后端代码将实现这个接口),并携带url参数,后端将拿到url做处理,最终返回授权结果,并进行验证,这里对应第4步骤

<script setup lang="ts">
import { onMounted } from 'vue';
import axios from 'axios';
import * as dd from 'dingtalk-jsapi';
onMounted(async () => {let resConfig: any = await axios({headers: {'Content-Type': 'application/json'},method: 'get',url: 'http://192.168.1.63:3000/jsSdkAuthorized',params: {url: location.href.split('#')[0]}});// console.log(location);if (resConfig.data.code == 200) {let { agentId, corpId, timeStamp, nonceStr, signature } = resConfig.data.signatureObj;console.log('signatureObj', agentId, corpId, timeStamp, nonceStr, signature);dd.config({agentId, // 必填,微应用IDcorpId, //必填,企业IDtimeStamp, // 必填,生成签名的时间戳nonceStr, // 必填,自定义固定字符串。signature, // 必填,签名type: 0, //选填。0表示微应用的jsapi,1表示服务窗的jsapi;不填默认为0。该参数从dingtalk.js的0.8.3版本开始支持jsApiList: ['biz.contact.choose'] // 必填,需要使用的jsapi列表,注意:不要带dd。});dd.ready(() => {console.log('ok');});dd.error(function (err) {console.log('dd error: ' + JSON.stringify(err));}); //该方法必须带上,用来捕获鉴权出现的异常信息,否则不方便排查出现的问题}
});
</script><template><div class="container">red润</div>
</template><style scoped lang="scss">
.container {background-color: red;
}
</style>

后端实现 这里使用express框架 (代码较多,主入口文件在index.js,核心授权代码在utils/sign.js中)

index.js后端主入口

解释下面的代码,

  • 后端收到前端发来的请求app.get("/jsSdkAuthorized")
  • 解析参数
  • 执行步骤1获取token
  • 执行步骤2获取ticket
  • 执行步骤3签名
  • 。。。

import express from 'express'
import cors from 'cors'
import config from "./datas/config.json" assert {type: "json"}
import { getAccessToken } from './utils/getAccessToken.js'import { getRandomStr, sign } from './utils/sign.js'
import { getTicket } from './utils/getTicket.js'
const app = express()
const port = 3000app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: false }))app.get("/jsSdkAuthorized", async (req, res) => {
// 解析参数let url = req.query.url;// 步骤1let token = await getAccessToken();// 步骤2let jsapiTicket = await getTicket(token);// 应用id前端发送let agentId = config.AgentId;let corpId = config.CorpId;let timeStamp = Date.now();// let nonceStr = getRandomStr(16)let nonceStr = getRandomStr(16)// 步骤3let signature = sign(jsapiTicket, nonceStr, timeStamp, url);res.send({code: 200,signatureObj: {agentId,corpId,timeStamp,nonceStr,signature}})
})app.listen(port, () => {console.log(port + ":running")
})

api/index.js 后端发送的请求

import axios from "axios";
const BASE_URL = "https://api.dingtalk.com/v1.0/oauth2";/*** 获取token* @param {*} appKey * @param {*} appSecret * @returns */
export const accessToken = async (appKey, appSecret) => {let data = await axios({headers: {'Content-Type': 'application/json'},method: 'post',url: `${BASE_URL}/accessToken`,data: {appKey,appSecret}});return data.data
}
/*** 获取jsapiTicket* @param {*} token * @returns */
export const jsapiTicket = async (token) => {try {let data = await axios({headers: {'Content-Type': 'application/json','x-acs-dingtalk-access-token': token},method: 'post',url: `${BASE_URL}/jsapiTickets`,data: {}});return data.data} catch (error) {console.log(error, 'error')}
}

datas/config.json 配置参数

{"AppKey": "xxx","AppSecret": "xxx","AgentId": "xx","CorpId": "xxx"
}

utils/getAccessToken.js 获取token,并且缓存

import fs from 'fs';
import { fileURLToPath } from 'url';
import path from 'path';
// 只读,不修改
import config from '../datas/config.json' assert {type: "json"}
import { accessToken } from '../api/index.js';
const appKey = config.AppKey;
const appSecret = config.AppSecret;const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// console.log(__filename, __dirname, '__filename,__dirname')export const getAccessToken = async () => {// 判断当前token是否存在,如果存在就获取当前的token,如果存在,但是过期了,就重新生成token,如果没有token,那也重新生成token// 获取当前的时间let currentTime = Date.now();// 获取本地的存放的accesstokenlet accessTokenJson = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../datas/token.json")));// 如果失效,重新请求if (accessTokenJson.accessToken == '' || accessTokenJson.expireIn < currentTime) {console.log("token失效");// 获取新的tokenconsole.log("get remote: token");let data = await accessToken(appKey, appSecret);accessTokenJson.accessToken = data.accessToken;// expires_in单位秒 5分钟 accessTokenJson.expireIn = Date.now() + (data.expireIn - 300) * 1000;fs.writeFileSync(path.resolve(__dirname, "../datas/token.json"), JSON.stringify(accessTokenJson));return accessTokenJson.accessToken} else {// 从本地获取console.log("get local: token");return accessTokenJson.accessToken;}
}

utils/getTicket.js 获取ticket并且缓存

import fs from 'fs';
import { fileURLToPath } from 'url';
import path from 'path';
// 只读,不修改
import { jsapiTicket } from '../api/index.js'const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// console.log(__filename, __dirname, '__filename,__dirname')export const getTicket = async (token) => {// 判断当前ticket是否存在,如果存在就获取当前的ticket,如果存在,但是过期了,就重新生成ticket,如果没有ticket,那也重新生成ticket// 获取当前的时间let currentTime = Date.now();// 获取本地的存放的accessticketlet accessTicket = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../datas/ticket.json")));// 如果失效,重新请求if (accessTicket.jsapiTicket == '' || accessTicket.expireIn < currentTime) {console.log("ticket失效");// 获取新的ticketconsole.log("get remote: ticket");let data = await jsapiTicket(token);accessTicket.jsapiTicket = data.jsapiTicket;// expires_in单位秒 5分钟 accessTicket.expireIn = Date.now() + (data.expireIn - 300) * 1000;fs.writeFileSync(path.resolve(__dirname, "../datas/ticket.json"), JSON.stringify(accessTicket));return accessTicket.jsapiTicket} else {// 从本地获取console.log("get local: ticket");return accessTicket.jsapiTicket;}
}

utils/sign.js核心鉴权函数


// import CryptoJS from 'crypto-js'
// import crypto from 'crypto'
import sha1 from 'sha1'
/*** 计算dd.config的签名参数** @param {string} jsticket 通过微应用appKey获取的jsticket* @param {string} nonceStr 自定义固定字符串* @param {number} timeStamp 当前时间戳* @param {string} currentUrl 调用dd.config的当前页面URL* @returns {string}*/
export const sign = (ticket, nonce, timeStamp, url) => {let plainTex = `jsapi_ticket=${ticket}&noncestr=${nonce}&timestamp=${timeStamp}&url=${decodeURIComponent(url)}`;let signature = sha1(plainTex);return signature;
}
/*** 生成随机字符串** @param {number} count 随机字符串长度* @returns {string}*/
export const getRandomStr = (count) => {const base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';let result = '';for (let i = 0; i < count; i++) {const randomIndex = Math.floor(Math.random() * base.length);result += base[randomIndex];}return result;
}
/*** 返回随机字符串* @returns */
export const getNonceStr = () => {return Math.random().toString(16).substring(2, 15)
}

最终效果
前端控制台输出

ok

写在最后!官方文档没有提供nodejs代码,差评,提供的文档不够详细,差评。还是前端不够被重视,认为后端就是java或php才能干。。。。

http://www.mnyf.cn/news/38146.html

相关文章:

  • 哪个网站网页做的好看电商培训机构推荐
  • wordpress如何使用一个demoseo的五个步骤
  • 做美剧盗版网站成人短期培训学校
  • 做网站需要招什么条件如何开一个自己的网站
  • wordpress怎么修改栏目标题百度关键词相关性优化软件
  • 邢台建网站站长网站seo查询
  • 莫名接到网站建设电话外汇交易平台
  • 什么网站可以快速做3d效果图如何在百度推广自己
  • 广东旅游网站建设百度推广关键词怎么优化
  • 工作室做网站流程深圳seo优化公司搜索引擎优化方案
  • 没有网站做分类信息群发百度应用平台
  • 四川省建筑信息网公司seo排名优化
  • 英铭科技做网站和设计制作更专业品牌策略怎么写
  • 温州商城网站建设如何创建自己的网站
  • 吉安律师网站建设做网络推广怎么收费
  • 做测评的网站网站优化是做什么的
  • 网站开发结论百度搜索网
  • 网站被k多久恢复长春网站建设开发
  • 网易企业邮箱服务器怎么设置石家庄seo推广优化
  • 石家庄网站建设多少钱一级域名生成二级域名
  • 2018年做淘宝客网站还能挣钱吗上海推广seo
  • 电子商务网站建设教程 pdf网络营销专业是干嘛的
  • 东莞营销型网站建设优化师的工作内容
  • 网页搜索关键词快捷键株洲seo快速排名
  • 西三旗网站建设网站产品怎么优化
  • 做VIP视频网站赚钱seo手机排名软件
  • wordpress 拖动分类百度seo优化方法
  • 创意合肥网站建设seo综合查询
  • 青岛做网站费用潍坊关键词优化排名
  • 网站建设需要的专业知识关键词搜索优化公司