如何保证API不被别人恶意调用

2019-07-28 14:11:08 浏览数 (1)

这两天比较悠闲,有很多时间可以用来写文章。扯扯淡,哈哈哈今天给大家分享一个纯业务的的东西,也会有代码辅助,但是不多。看名字是不是都觉得很屌哈哈哈哈哈哈哈。 博主是一个标题党。

先给你们上一张小编自己画的图吧。我不知道大家写APi的时候有没有这样的疑惑。。

就是api频繁被恶意调用,有没有这种的,我擦我新写的接口又被爬去了,竟然拼接了参数来不断请求。哎。。。。。

来听小编发生在自己身上的超级恶心的bug

我记得小编在上家公司遇到一个很奇葩的事,我刚写了一个发短信的接口,感觉自己浑身都飘起来了,

并对我说了一生,大猪蹄子你这个功能没问题可以正常上线。。。 可以上线正式版本,我习以为常的就上线了。 正当我和小姐姐聊天呢,我们Leader拿着个菜刀就过了,小伙子你要逆天啊。。。

我说咋的咋的了,是不是泡你妹子了。我们leader拿着一个账单

你给我哦解释一下,咱们的程序刚上线每一个月,短信费用干了5w多 是不是用户多了,leader说md用户还是那几个我们自己人 然后我看了一下某短信平台嘚消费信息,结果真的发送了这么多验证码。

是不是短信平台出bug了。。。我给老板说得赶紧维权啊

结果给客服小姐姐打电话打了2个小时,最后的结局是我们平台没有bug,一切正常。是你们频繁调用我们接口的。我就怒了,妈的什么破短信平台,垃圾。。。。吞钱啊。。

没办法了,找自身原因吧,我默默打开xsheel 一看日志 我他妈顿时就惊呆了。还在刷验证码 我什么都没有想,就把服务器Tomcat就给关了,结果一个小时损失了几个亿日元。。。。

妈的Leader差点被砍死。。。。。还好我命大。

最后发现了问题所在就是接口没有加认证,被大坏蛋恶意抓取了,然后只要给这个接口传手机,这个接口就开始发短信,我才他们写了一个for循环然后频繁调用我们接口。。。太他妈狠了。。。。。。。

这就是网上流传的短信轰炸机

小编副业写BUG 副业DBUg 哎做一个程序员真累。

(adsbygoogle =window.adsbygoogle ||[]).push({});


今天就给大家分享一个给API接口加认证的方法(只有业务)

我画了一个流程图,先给你们看看~~~~

kingYifan用了20年的画工才花出来的。。。(不喜欢勿喷啊)

来给你们贴代码的时候到了

代码语言:javascript复制
  /***
	*spring mvc的请求过滤,权限验证
	*KingYiFan
	*/
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		String path = request.getServletPath();
		//走正则表达式 看是否这个接口是否需要认证
		if(path.matches(Const.NO_INTERCEPTOR_PATH)){
			//不需要直接放行
			return true;
		}
		Map<String,Object> map = new HashMap<String,Object>();
		//接受前台的数据 sign是加密的字符串
		String sign = request.getParameter("sign");
		//前台的时间戳
		String timestamp = request.getParameter("timestamp");
		//用户的凭证,这个根据业务写
		String token =request.getHeader("token");
		//判断是否为空 为空直接返回false
		if(Tools.notEmpty(sign)&&(Tools.notEmpty(timestamp)&×tamp.length()==13)) {
			//验证请求超时
			Long _timestamp = Long.parseLong(timestamp);
			if (System.currentTimeMillis()/1000 -  _timestamp * 1000 > 60 * 1000) {
				map = AppUtil.returnResult(map,"fail",Const.PROMPT_TIMEOUT);
				logger.info("接口访问失败,请求超时,访问路径:----" path);
				println(response, map);
				return false;
			}
			//验证签名
			//String param = path.substring(path.lastIndexOf("/") 1, path.length());
			boolean signBool = AppUtil.checkSign(token, sign, timestamp);
			if(!signBool){
				map = AppUtil.returnResult(map,"fail",Const.PROMPT_WRONGFUL);
				logger.info("接口访问失败,验签不正确,访问路径:----" path);
				println(response, map);
				return false;
			}
		}else {
			map = AppUtil.returnResult(map,"fail",Const.PROMPT_WRONGFUL);
			logger.info("接口访问失败,验签不正确,访问路径:----" path);
			println(response, map);
			return false;
		}
		logger.info("接口访问成功,访问路径:----" path); 
		return true;
	}

对比的工具类(签名)

代码语言:javascript复制
/**
	 * 检测KEY是否正确
	 * @param paraname  传入参数
	 * @param FKEY		接收的 KEY
	 * @return 为空则返回true,不否则返回false
	 */
	public static boolean checkSign(String paraname, String sign,String timestamp){
		paraname = (null == paraname)? "":paraname;
		return MD5.md5(paraname ",cnbuilder.cn," timestamp).equalsIgnoreCase(sign);
	}

上面就是一套验签的服务器端流程,有什么不懂就联系我。

0 人点赞