首页 > 编程语言 >我的小程序接口被刷爆了

我的小程序接口被刷爆了

时间:2024-04-13 09:22:27浏览次数:13  
标签:return String 程序接口 程序 sign json signStr

自然流量的惊喜

      书接上文,凭着短视频的好奇,搭了个小程序,做了文案提取,配音等功能,也顺带写了两篇口水文章,不曾想居然收获历史最高的点赞与收藏。有兴趣的朋友可以点这里一看究尽:《短视频配音原来如此简单》,《短视频文案提取的简单实现》。做为一个食人间烟火的程序员,也偷偷的去看了数据,由于没抱太大的期望,自然流量给了我一个大大的惊喜,下图是没有任何推广的数据。我一度暗暗自喜,直到我上线了另一个小程序做对照组时,也就是上两个文章中提到的小程序,几乎没有自然流量,即使这个小程序功能更全,体验更好,所有用户都是从我的文章中关联而来的,没有自然流量。我瞬间明白了:论小程序取名的重要性。

 

 

告警呼啸而至

        小程序上线后,总于可以睡上安稳觉了。于是又开始早上6:30去学校带小朋友跑步了。跑了一年了,好几个小朋友算是跑上道了。跑得正酣畅淋漓之时,突然,企微告警群开始咚咚告警:resource pack exhausted! Please purchase resource packs... 30小时的资源包才买几天怎么就耗尽了呢。跑完步,在学校噌了早饭,小电驴儿一溜烟回家打开电脑,巴拉出访问日志,傻眼了。这样一个没名没份的小程序,居然有人在刷它的接口(大部分都是视频文案提取,原来还有这么多人在做短视频),心中顿感五味杂成,有人刷说明功能还不多,这样刷地主家也没有余粮了...

 

 

签名保驾护航

        既然来了,只能接招了。既然刷接口,那就对接口访问做一些校验。目前小程序只是提文案提取等功能,所以首先想到接口做个签名,防止别人使用程序自动刷。考虑小程序源码获取比较困难,签名字段根据sha1简单生成就可以了,未来如果这个也行不通,再使用RSA加密下sign字段就可以了。sign生成规则比较简单,timestamp,request,随机串,请求参数,排序 sha1就可以了。代码如下。

前端只需要在request中 生成签名,放到header里就行了。

function sign(json) {
  json.timestamp = getTimestamp();
  json.rand = mtRand(100000, 999999);
  json.appkey = app.globalData.secretKey;

  let valueArray = [];
  for (let key in json) {
    valueArray.push(json[key]);
  }
  valueArray.sort();

  let signStr = jsonVAL(valueArray);
  console.log("signStr", signStr);

  json.sign = sha1Util.sha1(signStr);
  delete json.appkey;
  return json;
}

 

后端也简单,根据一样的规则,一样的key,生成sign,对比前端的sign字段就可以了。自定义HandlerInterceptor,并注册到InterceptorRegistry中就。

代码如下;

/**
 * sign校验拦截器
 * @author JJ
 */
@Slf4j
@Component
public class CheckSignInterceptor implements HandlerInterceptor {

    private static final String SecretKey = "*******";
    // 签名过期时间(s)
    private static final Integer TimestampOut = 300;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {


        RequestWrapper requestWrapper = new RequestWrapper(request);
        String body = requestWrapper.getBody();
        Result result = this.check(body);
        if (!result.getSuccess()) {
            log.info("签名失败:{}", body);
            // 设置状态码为401,表示未授权
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            // 设置响应内容类型和字符集
            response.setContentType("application/json;charset=UTF-8");
            // 自定义输出
            response.getWriter().write(JSONUtil.toJsonStr(result));
            // 返回false阻止后续处理
            return false;
        }
        return true;
    }

    /**
     * token校验
     * @param token
     * @return
     */
    private Result check(String body) {

        JSONObject jsonObject = JSONUtil.parseObj(body);
        String sign = "";
        Long timestamp = 0L;
        // jsonObject 值输入有序列表。
        List<String> paramsValueList = new ArrayList<>();
        Set<Map.Entry<String, Object>> entries = jsonObject.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (key.equals("sign")){
                sign = value.toString();
                continue;
            }
            if (key.equals("timestamp")){
                //如果时间戳为空
                if (Strings.isNullOrEmpty(value.toString())){
                    return Result.failed(ErrorCodeEnum.ILLEGAL_ARGUMENT.code(), "时间戳不能为空");
                }
                timestamp = Long.parseLong(value.toString());
            }
            paramsValueList.add(value.toString());
        }
        paramsValueList.add(SecretKey);
        Collections.sort(paramsValueList);

        //判断时间是否大于5分钟
        if (System.currentTimeMillis()/1000 - timestamp > TimestampOut){
            //return Result.failed(ErrorCodeEnum.ILLEGAL_ARGUMENT.code(), "时间戳无效");
        }
        String signStr = "";
        for (String value : paramsValueList) {
            signStr += value;
        }
        log.info("signStr:{}", signStr);
        String sha1Str = SecureUtil.sha1(signStr);
        if (sha1Str.equals(sign)){
            return Result.success();
        }
        return Result.failed(ErrorCodeEnum.ILLEGAL_ARGUMENT.code(), "签名失败");
    }

}

 

/**
 * @author JJ
 * @Classname InterceptorConfig
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Resource
    CheckTokenInterceptor checkTokenInterceptor;
    @Resource
    CheckSignInterceptor checkSignInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(checkSignInterceptor).order(1);
       
    }
}

 

以上代码基本都是copy的原有代码,没半天就上线了,自以为可以高枕无忧了。

 

啥也挡不住RPA

       上线后,购买了资源包,也提心吊胆的统计着使用量。过了办天,又有几个用户提取了超过70条视频的文案。我一度怀疑签名没生效,直到我看非常规律的调用,我知道了,RPA来了。之前公司买过一个叫影刀RPA软件,也玩了一些时间,编写过一些自动化任务。它可以模拟人操作行为,完成自动化任务,当然,我一直认为未来RPA会有更多业务场景,一些逻辑明确的重复的事,都会由它们来完成。难怪小程序数据里有不少是从pc打开的。我意识到我被薅羊毛了。

 

无奈只能限量了

       本着大家都有机会体验这个小程序的原则,无奈之下,只能给每人每日限量了,毕竟小程序没有收入。再本着能每个人都有极致体验的机会,我限制了每人每天每个功能30次。这下基本上都限制到了,但是看着那些个RPA机器人,一大早就毫无感情的把30次机会耗尽,于是又增加了按UserId配置额度的功能,优先级高于按功能分配的额度。一顿操作后,总算是基本控制住了。又心累又心喜。喜在小程序给部分人带来了价值,即便是用RPA的那些人也是有价值,虽然没有感情。累的是又不得不处理这些烦琐之事。

 

写在最后

最近短剧火了起来,就有不少人开始提取长视频的文案以及长视频去水印。考虑到微信保存视频时,有个200M的限制,又在考虑支持视频文件压缩功能了。跟本停不下来了,把写代码当成乐趣也是不错的一件事儿。

 

有兴趣的同学可以扫码体验下小程序(小程序名称正在申请修改名称,建议扫码)

小程序名称 :智能配音实用工具;

小程序二维码 : 

 

标签:return,String,程序接口,程序,sign,json,signStr
From: https://www.cnblogs.com/jijunjian/p/18132500

相关文章

  • uniapp 小程序接口调用封装
    目的:接口封装让代码更简洁,操作更方便,出错率更低。第一步:建立引用目录 第二步:封装request.jsconstBASE_URL="http://"//公共请求头地址constrequest=(url,method,data)=>{ returnnewPromise((resolve,reject)=>{ uni.request({ url:BASE_URL+url,......
  • 商业银行应用程序接口安全管理
    1、商业银行应用程序接口分为两类,一是资金交易与账户信息查询应用类,级别相对较高。二是金融产品和服务信息查询应用类,级别相对较低。2、接口安全设计。一是身份认证,包括接口身份认证和用户身份认证。接口身份认证主要是APPID与APP_Secret、数字证书、公私钥对的组合。用户身......
  • Linux内核驱动程序接口 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/process/stable-api-nonsense.html#binary-kernel-interfaceLinux内核驱动程序接口(回答你的所有问题以及更多)[email protected]这篇文章旨在解释为什么Linux没有二进制内核接口,也没有稳定的内核接口。注意请注意......
  • 前端小程序接口报错error:60001
    昨天发版过程中发现,测试环境好好的接口到生产就报错了,后台直接接收不到,我们请求的接口根本没有进行后台,查看报错原因如下: 通过排除原因:1.其它接口有没问题2.请求域名是否一致3.请求方式是否一致4.是否有做token限制最后查到原因:其余接口没有问题,......
  • 写程序接口常遇到的20个坑
    跨域问题:在接口调用时,如果出现跨域问题需要在服务器端配置CORS(跨域资源共享)。参数校验不完善:需要对接口传入的参数进行校验,确保参数的合法性和完整性。接口安全问题:需要对接口进行身份验证和权限控制,避免未经授权的请求对系统造成损害。接口性能问题:在设计接口时需要考虑接口......
  • 应用程序接口(API)安全的入门指南
    ​ 什么是API?​对于初学者来说,API是指为两个不同的应用之间实现流畅通信,而设计的应用程序编程接口。它通常被称为应用程序的“中间人”。由于我们需要保护用户的持有数据、以及应用本身的完整性,因此API的安全性是一种“刚需”。而对于开发人员而言,API是一个非常好的工具......
  • Microsoft ODBC Driver是由Microsoft开发的用于ODBC(开放式数据库连接)的驱动程序。ODBC
    MicrosoftODBCDriver是由Microsoft开发的用于ODBC(开放式数据库连接)的驱动程序。ODBC是一种标准的应用程序接口,用于通过数据库管理系统(DBMS)访问和处理数据库。MicrosoftODBCDriver为开发人员提供了与各种数据库进行连接和交互的功能。它支持多个数据库系统,包括MicrosoftSQLS......
  • ActiveMQ学习(四)——应用程序接口…
    在Java里有JMS的多个实现。其中apache下的ActiveMQ用ActiveMQ最好还是了解下JMSJMS公共点对点域发布/订阅域ConnectionFactoryQueueConnectionFactoryTopicConnectionFactoryConnectionQueueConnectionTopicConnectionDestinationQueueTopicSessionQueueSessionTopicSes......
  • Qt应用程序接口和插件的创建详细过程
    Qt应用程序接口:包含类定义的头文件(*.h),该类定义中一般只包含纯虚函数的声明。Qt应用程序插件:继承自指定类和接口的C++类,该类实现了接口中定义的纯虚函数。 ------------......
  • 小程序接口请求的初次封装
    我们在写微信小程序中不管是用原生的微信开发者工具还是用uniapp来开发都需要用到数据的请求,在页面中大量的使用请求无疑会造成代码的冗余,也会给后期的维护带来很大的难......