springboot+activiti7+react实现模仿钉钉功能的审批流(十一、外部系统通过api发起流程)

参数及说明:

processCode:表单列表里面的编码

接口调用:

注意:流程发起成功之后,需要存一下返回的流程实例id,这里的作用请结合《十二、通知外部系统流程状态变化》查阅

发起之后可以在流程里面看到:

发起流程如果提供给外部使用,特别是互联网接口,请使用接口签名;

方案:

请求头携带参数appId+timestamp+nonce+sign,只有1.拥有合法的身份appId和正确的签名sign 2.timestamp10分钟内、nonce未被使用才能放行。这样就解决了身份验证和参数篡改问题,即使请求参数被劫持,由于获取不到appSecret(仅作本地加密使用,不参与网络传输),无法伪造合法的请求。

一个测试用例:

/**
     * 第三方接口签名方法测试
     * 主要实现以下两条:
     * 1.防止篡改
     * 参数签名
     * 按照请求header的字母升序排列非空请求参数(包含appId),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA
     * 按照请求body的字母升序排列非空请求参数,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringB
     * (这里将参数header和体分开,避免参数覆盖-header里面的参数名和头参数key相同)
     * stringA+stringB+appSecret得到字符串stringSignTemp;
     * 对stringSignTemp进行sha256签名运算,并将得到的字符串所有字符转换为大写,得到sign值。
     * <p>
     * 2.重放攻击
     * timestamp+nonce方案
     * nonce指唯一流水号,用来标识每个被签名的请求。通过为每个请求提供一个唯一的标识符,服务器能够防止请求被多次使用(记录所有用过的nonce以阻止它们被二次使用)。
     * 然而,对服务器来说永久存储所有接收到的nonce的代价是非常大的。可以使用timestamp来优化nonce的存储。
     * 假设允许客户端和服务端最多能存在10分钟的时间差,同时追踪记录在服务端的nonce集合。当有新的请求进入时,首先检查携带的timestamp是否在10分钟内,
     * 如超出时间范围,则拒绝,然后查询携带的nonce,如存在已有集合,则拒绝。否则,记录该nonce,并删除集合内时间戳大于10分钟的nonce(可以使用redis的expire,新增nonce的同时设置它的超时失效时间为10分钟)。
     * <p>
     * <p>
     * 请求头携带参数appId+timestamp+nonce+sign,只有1.拥有合法的身份appId和正确的签名sign 2.timestamp10分钟内、nonce未被使用才能放行。
     * 这样就解决了身份验证和参数篡改问题,即使请求参数被劫持,由于获取不到appSecret(仅作本地加密使用,不参与网络传输),无法伪造合法的请求。
     * <p>
     * 还可以加上IP白名单校验
     */
    @Test
    public void createSign() {
        //appId和加密密钥,由服务提供方给
        String appId = "100001";
        String appSecret = "80f740fec04a5e7daebd8dd02ca4f69c";
        //参数-header
        Map<String, Object> header = new HashMap<>();
        //app标识-标识来自于哪个第三方应用
        header.put("appId", appId);
        //使用雪花算法生成流水id
        Snowflake snowflake = IdUtil.getSnowflake(1, 1);
        header.put("nonce", snowflake.nextId());
        //时间戳-接口有效期,比如此调用超过10分钟失效
        header.put("timestamp", System.currentTimeMillis());
        //根据参数排序后拼接为字符串,常用于签名
        String stringA = MapUtil.sortJoin(header, "&", "=", true);
        log.info("{}", stringA);

        //参数-body
        Map<String, Object> body = new HashMap<>();
        body.put("name", "hello");
        body.put("home", "world");
        body.put("work", "java");
        String stringB = MapUtil.sortJoin(body, "&", "=", true);
        log.info("{}", stringB);

        //生成签名--使用摘要算法
        String stringSignTemp = stringA + stringB + appSecret;
        //头数据字符串+请求参数字符串+key
        String sign = SecureUtil.sha256(stringSignTemp);
        log.info("{}", sign.toUpperCase());
    }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小绿豆

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值