专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

SpringBoot如何保证接口安全?老鸟们都是这么玩的!

  对于互联网来说,只要你系统的接口暴露在外网,就避免不了接口安全问题。如果你的接口在外网裸奔,只要让黑客知道接口的地址和参数就可以调用,那简直就是灾难。
  举个例子:你的网站用户注册的时候,需要填写手机号,发送手机验证码,如果这个发送验证码的接口没有经过特殊安全处理,那这个短信接口早就被人盗刷不知道浪费多少钱了。
  那如何保证接口安全呢?
  一般来说,暴露在外网的api接口需要做到防篡改和防重放才能称之为安全的接口。防篡改
  我们知道http是一种无状态的协议,服务端并不知道客户端发送的请求是否合法,也并不知道请求中的参数是否正确。
  举个例子,现在有个充值的接口,调用后可以给用户增加对应的余额。http:localhostapiuserrecharge?userid1001amount10
  如果非法用户通过抓包获取到接口参数后,修改userid或amount的值就可以实现给任意账户添加余额的目的。如何解决
  采用https协议可以将传输的明文进行加密,但是黑客仍然可以截获传输的数据包,进一步伪造请求进行重放攻击。如果黑客使用特殊手段让请求方设备使用了伪造的证书进行通信,那么https加密的内容也会被解密。
  一般的做法有2种:采用https方式把接口的数据进行加密传输,即便是被黑客破解,黑客也花费大量的时间和精力去破解。接口后台对接口的请求参数进行验证,防止被黑客篡改;
  步骤1:客户端使用约定好的秘钥对传输的参数进行加密,得到签名值sign1,并且将签名值也放入请求的参数中,发送请求给服务端步骤2:服务端接收到客户端的请求,然后使用约定好的秘钥对请求的参数再次进行签名,得到签名值sign2。步骤3:服务端比对sign1和sign2的值,如果不一致,就认定为被篡改,非法请求。防重放
  防重放也叫防复用。简单来说就是我获取到这个请求的信息之后什么也不改,,直接拿着接口的参数重复请求这个充值的接口。此时我的请求是合法的,因为所有参数都是跟合法请求一模一样的。
  重放攻击会造成两种后果:针对插入数据库接口:重放攻击,会出现大量重复数据,甚至垃圾数据会把数据库撑爆。针对查询的接口:黑客一般是重点攻击慢查询接口,例如一个慢查询接口1s,只要黑客发起重放攻击,就必然造成系统被拖垮,数据库查询被阻塞死。
  对于重放攻击一般有两种做法:基于timestamp的方案
  每次HTTP请求,都需要加上timestamp参数,然后把timestamp和其他参数一起进行数字签名。因为一次正常的HTTP请求,从发出到达服务器一般都不会超过60s,所以服务器收到HTTP请求之后,首先判断时间戳参数与当前时间比较,是否超过了60s,如果超过了则认为是非法请求。
  一般情况下,黑客从抓包重放请求耗时远远超过了60s,所以此时请求中的timestamp参数已经失效了。如果黑客修改timestamp参数为当前的时间戳,则sign1参数对应的数字签名就会失效,因为黑客不知道签名秘钥,没有办法生成新的数字签名。
  但是这种方式的漏洞也是显而易见,如果在60s之内进行重放攻击,那就没办法了,所以这种方式不能保证请求仅一次有效。
  老鸟们一般会采取下面这种方案,既可以解决接口重放问题,又可以解决接口一次请求有效的问题。基于noncetimestamp的方案
  nonce的意思是仅一次有效的随机字符串,要求每次请求时该参数要保证不同。实际使用用户信息时间戳随机数等信息做个哈希之后,作为nonce参数。
  此时服务端的处理流程如下:去redis中查找是否有key为nonce:{nonce}的string如果没有,则创建这个key,把这个key失效的时间和验证timestamp失效的时间一致,比如是60s。如果有,说明这个key在60s内已经被使用了,那么这个请求就可以判断为重放请求。
  这种方案nonce和timestamp参数都作为签名的一部分传到后端,基于timestamp方案可以让黑客只能在60s内进行重放攻击,加上nonce随机数以后可以保证接口只能被调用一次,可以很好的解决重放攻击问题。代码实现
  接下来通过实际代码来看看如何实现接口的防篡改和防重放。1、构建请求头对象DataBuilderpublicclassRequestHeader{privateStringsign;privateLongtimestamp;privateStringnonce;}2、工具类从HttpServletRequest获取请求参数Slf4jUtilityClasspublicclassHttpDataUtil{post请求处理:获取Body参数,转换为SortedMapparamrequestpublicSortedMapString,StringgetBodyParams(finalHttpServletRequestrequest)throwsIOException{byte〔〕requestBodyStreamUtils。copyToByteArray(request。getInputStream());StringbodynewString(requestBody);returnJsonUtil。json2Object(body,SortedMap。class);}get请求处理:将URL请求参数转换成SortedMappublicstaticSortedMapString,StringgetUrlParams(HttpServletRequestrequest){Stringparam;SortedMapString,StringresultnewTreeMap();if(StringUtils。isEmpty(request。getQueryString())){returnresult;}try{paramURLDecoder。decode(request。getQueryString(),utf8);}catch(UnsupportedEncodingExceptione){e。printStackTrace();}String〔〕paramsparam。split();for(Strings:params){String〔〕arrays。split();result。put(array〔0〕,array〔1〕);}returnresult;}}
  这里的参数放入SortedMap中对其进行字典排序,前端构建签名时同样需要对参数进行字典排序。3、签名验证工具类Slf4jUtilityClasspublicclassSignUtil{验证签名验证算法:把timestampJsonUtil。object2Json(SortedMap)合成字符串,然后MD5SneakyThrowspublicbooleanverifySign(SortedMapString,Stringmap,RequestHeaderrequestHeader){StringparamsrequestHeader。getNonce()requestHeader。getTimestamp()JsonUtil。object2Json(map);returnverifySign(params,requestHeader);}验证签名publicbooleanverifySign(Stringparams,RequestHeaderrequestHeader){log。debug(客户端签名:{},requestHeader。getSign());if(StringUtils。isEmpty(params)){returnfalse;}log。info(客户端上传内容:{},params);StringparamsSignDigestUtils。md5DigestAsHex(params。getBytes())。toUpperCase();log。info(客户端上传内容加密后的签名结果:{},paramsSign);returnrequestHeader。getSign()。equals(paramsSign);}}4、HttpServletRequest包装类publicclassSignRequestWrapperextendsHttpServletRequestWrapper{用于将流保存下来privatebyte〔〕requestBodynull;publicSignRequestWrapper(HttpServletRequestrequest)throwsIOException{super(request);requestBodyStreamUtils。copyToByteArray(request。getInputStream());}OverridepublicServletInputStreamgetInputStream()throwsIOException{finalByteArrayInputStreambaisnewByteArrayInputStream(requestBody);returnnewServletInputStream(){OverridepublicbooleanisFinished(){returnfalse;}OverridepublicbooleanisReady(){returnfalse;}OverridepublicvoidsetReadListener(ReadListenerreadListener){}Overridepublicintread()throwsIOException{returnbais。read();}};}OverridepublicBufferedReadergetReader()throwsIOException{returnnewBufferedReader(newInputStreamReader(getInputStream()));}}
  防篡改和防重放我们会通过SpringBootFilter来实现,而编写的filter过滤器需要读取request数据流,但是request数据流只能读取一次,需要自己实现HttpServletRequestWrapper对数据流包装,目的是将request流保存下来。5、创建过滤器实现安全校验ConfigurationpublicclassSignFilterConfiguration{Value({sign。maxTime})privateStringsignMaxTime;filter中的初始化参数privateMapString,StringinitParametersMapnewHashMap();BeanpublicFilterRegistrationBeancontextFilterRegistrationBean(){initParametersMap。put(signMaxTime,signMaxTime);FilterRegistrationBeanregistrationnewFilterRegistrationBean();registration。setFilter(signFilter());registration。setInitParameters(initParametersMap);registration。addUrlPatterns(sign);registration。setName(SignFilter);设置过滤器被调用的顺序registration。setOrder(1);returnregistration;}BeanpublicFiltersignFilter(){returnnewSignFilter();}}Slf4jpublicclassSignFilterimplementsFilter{ResourceprivateRedisUtilredisUtil;从fitler配置中获取sign过期时间privateLongsignMaxTime;privatestaticfinalStringNONCEKEYxnonce;OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{HttpServletRequesthttpRequest(HttpServletRequest)servletRequest;HttpServletResponsehttpResponse(HttpServletResponse)servletResponse;log。info(过滤URL:{},httpRequest。getRequestURI());HttpServletRequestWrapperrequestWrappernewSignRequestWrapper(httpRequest);构建请求头RequestHeaderrequestHeaderRequestHeader。builder()。nonce(httpRequest。getHeader(xNonce))。timestamp(Long。parseLong(httpRequest。getHeader(XTime)))。sign(httpRequest。getHeader(XSign))。build();验证请求头是否存在if(StringUtils。isEmpty(requestHeader。getSign())ObjectUtils。isEmpty(requestHeader。getTimestamp())StringUtils。isEmpty(requestHeader。getNonce())){responseFail(httpResponse,ReturnCode。ILLEGALHEADER);return;}1。重放验证判断timestamp时间戳与当前时间是否操过60s(过期时间根据业务情况设置),如果超过了就提示签名过期。longnowSystem。currentTimeMillis()1000;if(nowrequestHeader。getTimestamp()signMaxTime){responseFail(httpResponse,ReturnCode。REPLAYERROR);return;}2。判断noncebooleannonceExistsredisUtil。hasKey(NONCEKEYrequestHeader。getNonce());if(nonceExists){请求重复responseFail(httpResponse,ReturnCode。REPLAYERROR);return;}else{redisUtil。set(NONCEKEYrequestHeader。getNonce(),requestHeader。getNonce(),signMaxTime);}booleanaccept;SortedMapString,StringparamMap;switch(httpRequest。getMethod()){caseGET:paramMapHttpDataUtil。getUrlParams(requestWrapper);acceptSignUtil。verifySign(paramMap,requestHeader);break;casePOST:paramMapHttpDataUtil。getBodyParams(requestWrapper);acceptSignUtil。verifySign(paramMap,requestHeader);break;default:accepttrue;break;}if(accept){filterChain。doFilter(requestWrapper,servletResponse);}else{responseFail(httpResponse,ReturnCode。ARGUMENTERROR);return;}}privatevoidresponseFail(HttpServletResponsehttpResponse,ReturnCodereturnCode){ResultDataObjectresultDataResultData。fail(returnCode。getCode(),returnCode。getMessage());WebUtils。writeJson(httpResponse,resultData);}Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{StringsignTimefilterConfig。getInitParameter(signMaxTime);signMaxTimeLong。parseLong(signTime);}}6、Redis工具类ComponentpublicclassRedisUtil{ResourceprivateRedisTemplateString,ObjectredisTemplate;判断key是否存在paramkey键returntrue存在false不存在publicbooleanhasKey(Stringkey){try{returnBoolean。TRUE。equals(redisTemplate。hasKey(key));}catch(Exceptione){e。printStackTrace();returnfalse;}}普通缓存放入并设置时间paramkey键paramvalue值paramtime时间(秒)time要大于0如果time小于等于0将设置无限期returntrue成功false失败publicbooleanset(Stringkey,Objectvalue,longtime){try{if(time0){redisTemplate。opsForValue()。set(key,value,time,TimeUnit。SECONDS);}else{set(key,value);}returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}普通缓存放入paramkey键paramvalue值returntrue成功false失败publicbooleanset(Stringkey,Objectvalue){try{redisTemplate。opsForValue()。set(key,value);returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}}

觉知当下的意义和要领问如果把工作当作觉知当下,那专注的时候是不是在觉知呢?答如果工作允许你觉知,就像扫地,是绝对可以觉知的。但是有些工作需要专注的时候,觉知力就变差了,就没有了。觉知的目的是在思想层面自己不改变,新的一年也只是之前的重演每年的一月份我都非常矛盾,害怕接受自己又老了一岁,但是又非常期待新的一年的到来。我总觉得新的一年,一切都可以重新开始,一切都可以重新洗牌,我也可以焕然一新!有好几年我都是在年初时信哪儿有什么永远的避风港?说个很残酷的事实,你真的无人可靠,而且永远都是孤独一人。无论是现在你跟某一个人在一起,有多快乐,也仅仅局限于当下。可以暂时依靠,但不要有长期依靠别人的想法,也永远不要把别人当做救世入不敷出的口袋我的生活也是头条一缕阳光照射着大地,有麦芽的清香,有油菜花的金黄,还有麦穗的手舞足蹈。我的生活就是鸡毛蒜皮,一地的烂泥。古人云,说出的委屈,哪都不是委屈。说出的困难,也不是困难能克终身无冠军就算了,还被第三次抛弃!保罗的命运好悲催,再见NBA也才几个月的时间,太阳从冠军级别的球队沦落到鱼腩行列,让我们看到了这支球队的脆弱和短板。一直对球权和战术地位心有戚戚的艾顿,在保罗和布克都不在场的时候,却没有能够发挥自己的作用,用梅罗对决!C罗梅开二度梅西破门造点巴黎54利雅得全明星北京时间1月20日凌晨1点,法甲球队巴黎圣日耳曼做客沙特,与利雅得全明星队进行一场热身赛,梅西与C罗分别代表两队首发出场。上半场,梅西在第3分钟就闪击破门,C罗制造点球并亲自罚进,梅西闪击破门C罗16分钟轰2球姆巴佩1球2助大巴黎54利雅得全明星北京时间1月20凌晨1点,利雅得全明星队在友谊邀请赛中对阵巴黎圣日耳曼,这是近段时间最受关注的一场重点比赛,这不仅是C罗来到沙特后的首场比赛,也是C罗与梅西的第37次同场对决,极有深夜传捷报!国乒三项大胜进决赛,女单5人进八强,男单有3人1月20日凌晨,WTT多哈常规挑战赛单打结束了八强争夺,国乒10人出战,8人进八强,其中女单5人,双打项目三项大胜,闯进决赛,可谓惊喜不断。双打混双真给力!三项进决赛,决战韩国夜深卡塔尔世界杯创下多个历史之最环球时报综合报道从172粒进球到50亿人次关注,卡塔尔世界杯创造了一系列新纪录。国际足联(FIFA)官方网站在2022年世界杯落幕后的一个月,披露了一系列重要数据,展现有史以来最好历届亚运会羽毛球女子单打冠军在上一篇我们回顾了历届亚运会羽毛球男子单打冠军,中国是在1974年开始继续参加亚运会,今天我们来盘点一下女子单打冠军1第七届伊朗德黑兰亚运会,1974年,陈玉娘,中国。2第八届泰国澳网第四日男单综述穆雷上演超级逆转,鲁德兹维爆冷出局!澳网男单下半区第二轮昨晚进行了多场紧张刺激的比赛,共诞生了三场输二赢三。且看详细战报卢布列夫62646763鲁苏沃里埃文斯646461查迪恩贝尔62676264库德拉鲁内75646
单说热度,今年火了3部古偶是不是一部现偶都没火?在国产剧市场,古装总是自带了一份观众缘,古装剧出爆款这件事说来并不稀奇。然而把梦华录放置在其中还是会觉得,这是很不一样的一张古装脸。梦华录脱胎于古代话本改编,以北宋作为时空展开叙事不会做开放世界就别做,好好的经典神作,是要亲手毁掉才甘心吗?要是说起塞尔达马里奥星之卡比这些经典的游戏作品,不知各位第一时间想到的是他们2D,还是3D的模样呢?这些大家熟知的游戏人物在时代演变之际也不断尝试往3D发展,甚至有些还成为3D动作山东曹县线上举办招商引资推介会资料图。近日,山东曹县举办线上招商引资推介会暨重点项目签约仪式,共签约项目16个,涉及生物医药高端化工新能源新材料等领域。据了解,近年来曹县立足生物医药高端化工等五大主导产业,坚持吴亦凡,终于为自己的风流付出了代价11月25日,被告人吴亦凡强奸聚众淫乱案一审宣判,决定执行有期徒刑13年,附加驱逐出境。对于北京市朝阳区人民法院一审公开审判的判决,网友们纷纷表示大快人心。法律面前人人平等,哪怕是5000多万人观看,这场年终演唱会看点在哪?冬日生活打卡季每到岁末年初,各大卫视都极尽所能花尽心思推出跨年演唱会陪伴观众跨年,12月28日晚8点,抖音跟天津卫视也一起办了场演唱会,这场演唱会共有八位歌手联唱,用户在2022年湖南台跨年晚会杨幂去油失败,金晨脚滑险摔跤,Twins疑似假喝跨年演唱会越来越卷了,显然,光拼明星已经满足不了观众的需求。于是,江苏卫视花重金把舞台与VR相结合,突出科技感。央视深耕文化领域,将暖心治愈走出新形式。湖南卫视更厉害了,直接三线并跨年晚会收视来了!杨幂创纪录,关晓彤紧急改妆,众星集体跑调2022年的最后一天,各大卫视的跨年晚会同时上演。从实时直播关注度来看,央视一骑绝尘,江苏和湖南卫视并驾齐驱,东方和北京卫视紧随其后。局长在各台晚会间来回切换,发现了不少亮点。这就湖南法院着力打击电信网络诈骗犯罪近日,湖南高院下发关于贯彻落实省十三届人大常委会第三十三次会议关于省人民政府关于打击治理电信网络诈骗违法犯罪工作情况的报告的审议意见的方案(以下简称方案),要求全省各级法院充分发挥央媒看湖南湖南新年伊始忙施工产业项目抢开局新华全媒湖南新年伊始忙施工产业项目抢开局新年伊始,制造业大省湖南的一批产业项目施工繁忙,园区和企业共同发力,为全年稳投资稳增长抢开局。工程机械是湖南的传统优势产业。在湖南省湘潭市的2023年最值得期待的13次天文奇观日食,月食流星雨我的生活也是头条宇宙科学2023年值得期待的天文事件日食和月食流星雨2023年值得期待的天文事件日食和月食流星雨从日食和月食到流星雨和超级月亮,以下是您可以在2023年期待的天文事在荆棘中寻找精神的家园费孝通先生在他那本著名的乡土中国里写道乡土社会是安土重迁的,生于斯长于斯死于斯的社会。自从进入农业社会以来,人类的衣食大致都要向土地索取,因此对土地产生了浓厚的依恋。我们的祖先将为
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网