摘要:下面舉幾個未經(jīng)保護的可能將會造成的安全事故通過抓包,找到發(fā)送短信驗證碼的。這可能將會直接對用戶造成財產(chǎn)損失。因此,未經(jīng)安全保護的非常的危險,對進行安全保護異常重要。可以將請求參數(shù)一并放入中,以此來確保數(shù)據(jù)的安全性。
未經(jīng)安全保護的API非常的危險
未經(jīng)安全保護的API非常的危險,其和裸奔無異。即使API文檔沒有被人為泄露,通過簡單的抓包也可以非常容易的獲取到API的URL以及對應的請求參數(shù)。下面舉幾個未經(jīng)保護的API可能將會造成的安全事故:
通過抓包,找到發(fā)送短信驗證碼的API。然后利用該API惡意的發(fā)送短信驗證碼。而發(fā)送短信驗證碼是需要收費的,這樣的惡意攻擊,將會導致無故的損失發(fā)送短信的費用。還會讓很多不明真相的吃瓜群眾收到奇怪的短信驗證碼,進而對產(chǎn)品產(chǎn)生不好的印象。
通過抓包,找到獲取用戶信息的API。該API的暴露,將會讓該平臺上所有用戶的信息被毫無保留的暴露在互聯(lián)網(wǎng)上。如果用戶信息中還涉及到一些重要的個人信息。比如身份證號,手機號等。將會讓用戶受到人生和財產(chǎn)的損失。
通過抓包,找到和財產(chǎn)相關的API。比如說修改訂單狀態(tài)的API。一旦該API暴露,黑客可以惡意的修改用戶的訂單狀態(tài)。比如說將訂單的狀態(tài)修改為取消。這可能將會直接對用戶造成財產(chǎn)損失。
上面這些例子僅僅只是筆者臨時想到的一些利用裸露API進行惡意攻擊的方式,實際中還存在著更多由于未對API進行加密,而造成損失的情況。因此,未經(jīng)安全保護的API非常的危險,對API進行安全保護異常重要。
什么是JWTJWT是json web token的縮寫。關于其如何確保數(shù)據(jù)傳輸?shù)陌踩缘奈恼履憧梢栽谒阉饕嫔险业胶芏?,在這里我將僅僅簡單介紹我對此的理解。
JWT可以理解為一串通過特定算法生成的字符串,在API的請求中,將這段字符串放入請求參數(shù)中。API Server通過判斷這段字符串是合法的還是偽造的,來確定這次API請求是否有效。通過該安全措施,將確保即使API被暴露,沒有生成JWT字符串的算法,也沒有辦法成功調(diào)用API。
JWT字符串分為兩個部分(官方的說法是分為3個部分),分別是‘未加密部分’和‘加密部分’。而‘加密部分’的內(nèi)容實際上是‘未加密部分’加密得到的。API Server檢查JWT字符串是否有效的第一步是將‘加密部分’解密然后與‘未加密部分’進行比較,查看是否內(nèi)容一致。如果內(nèi)容不一致,則說明該JWT字符串是偽造的。
JWT字符串中包括一個‘過期時間’的字段,當API Server獲取到JWT字符串后,可以通過檢查該字段與當前時間相比,是否已經(jīng)處于過期的狀態(tài)。如果‘過期時間’字段早于當前時間,則說明這次API請求是無效的。
你也可以在JWT字段種加入自定義的字段。然后在API Server獲取到JWT字段后,通過這些自定義的字段判斷是不是符合具體的業(yè)務邏輯,進而判斷這次請求是不是有效。
利用jjwt實現(xiàn)JWT對API的保護jjwt是java對JWT的封裝,下面的方法將會演示。在java中如何利用jjwt實現(xiàn)API的保護
gradle依賴compile "io.jsonwebtoken:jjwt:0.7.0"生成JWT字符串
public String buildJwt(Date exp) { String jwt = Jwts.builder() .signWith(SignatureAlgorithm.HS256,SECRET_KEY)//SECRET_KEY是加密算法對應的密鑰,這里使用額是HS256加密算法 .setExpiration(exp)//expTime是過期時間 .claim("key","vaule")//該方法是在JWT中加入值為vaule的key字段 .compact(); return jwt; }判斷JWT是否有效
public boolean isJwtValid(String jwt) { try { //解析JWT字符串中的數(shù)據(jù),并進行最基礎的驗證 Claims claims = Jwts.parser() .setSigningKey(SECRET_KEY)//SECRET_KEY是加密算法對應的密鑰,jjwt可以自動判斷機密算法 .parseClaimsJws(jwt)//jwt是JWT字符串 .getBody(); String vaule = claims.get("key", String.class);//獲取自定義字段key //判斷自定義字段是否正確 if ("vaule".equals(vaule)) { return true; } else { return false; } } //在解析JWT字符串時,如果密鑰不正確,將會解析失敗,拋出SignatureException異常,說明該JWT字符串是偽造的 //在解析JWT字符串時,如果‘過期時間字段’已經(jīng)早于當前時間,將會拋出ExpiredJwtException異常,說明本次請求已經(jīng)失效 catch (SignatureException|ExpiredJwtException e) { return false; } }Client端
Client端需要做的就是,根據(jù)API的需求將JWT字符串放入http請求中。我的做法是對于所有的API,在Client端生成JWT字段,然后將其添加到http請求的header中,確保所有的API都獲得保護。對于一些比較敏感的信息,再用加一層JWT驗證。比如說用戶信息,在調(diào)用登錄API后,API Server將會返回一個特定的JWT字符串,該JWT字段總將會包含該用戶的userId。如果要獲取用戶信息,除了要將Client端生成的JWT字段放入請求,還需要將該JWT字符串放入請求。接下來展示一下利用OKHttp在http請求的header中加入JWT字段的代碼:
//該方法將會在所有請求的header中加入jwt public Response call(Request request) throws IOException { OkHttpClient client = new OkHttpClient(); Request.Builder requestBuilder = request.newBuilder() .addHeader("commonJwt", jwtService.makeJwt());//加入Client本地生成的JWT字符串 //加入登錄成功后獲取到的JWT字符串 String userJwt = jwtService.getUserJwt(); if (!StringUtils.isSpace(userJwt)) requestBuilder.addHeader("userJwt", userJwt); request = requestBuilder.build(); return client.newCall(request).execute(); }API Server
API Server端需要做的就是,在收到API請求時,首先檢查client端生成的JWT字段是否有效,然后如果該API涉及敏感信息,則檢查檢測特定的JWT字段是否有效。接下來展示一下在spring中利用aop進行JWT字段的驗證:
@Pointcut("@annotation(org.springframework.web.bind.annotation.ResponseBody)") public void onCommonAuth(){} //所有的API都需要驗證client生成的JWT字段是否有效 @Order(1) @Around("onCommonAuth()") public Object onCommonAuth(ProceedingJoinPoint joinPoint) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String commonJwt = request.getHeader("commonJwt"); if (jwtService.isCommonJwtValid(commonJwt)) { return joinPoint.proceed(); } else { return "沒有訪問該API的權(quán)限"; } } @Pointcut("execution(* com.demo.controller.UserController.getUserInfo(..))") public void onGetByUserInfo() {} //對獲取用戶信息API,堅持userJwt是否有效 @Order(2) @Around("onGetByUserInfo()&&args(userId,..)") public Object onGetByUserInfo(ProceedingJoinPoint joinPoint, Long userId) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String userJwt = request.getHeader("userJwt"); if (jwtService.isUserJwtValid(userJwt, userId)) { return joinPoint.proceed(); } else { return "沒有訪問該API的權(quán)限"; } }補充
JWT在一定程度上,保護了API的安全。但是其本身還是存在一定的缺陷的。比如說,一定JWT的加密密鑰一旦被泄露,那么黑客就可以生成JWT字符串了,因此保護好JWT加密密鑰非常重要。
在上面的例子當中,介紹了獲取用戶信息API需要加入userJwt的例子。userJwt其實就是在JWT字符串中加入了userId字段,繼而保證一個userJwt只能訪問一個用戶的信息。對于其他的API,比如說PUT和POST操作,需要新增和修改數(shù)據(jù)的API??梢詫⒄埱髤?shù)一并放入jwt中,以此來確保數(shù)據(jù)的安全性。否則黑客還可以在JWT字符串還沒有過期的時間段內(nèi),修改請求中的參數(shù),達到攻擊的目的。
另外還要防止重復式攻擊,黑客還可以在JWT字符串還沒有過期的時間段內(nèi),重復提交請求,達到攻擊的目的。比如說新增訂單的API,如果被黑客采用重復式攻擊的方式,就會生成多個訂單。
參考RESTful Api 身份認證中的安全性設計探討
JSON Web Token - 在Web應用間安全地傳遞信息
八幅漫畫理解使用JSON Web Token設計單點登錄系統(tǒng)
How to Create and verify JWTs in Java
jwt官方介紹
jwt官網(wǎng)
jjwt在github上的地址
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66104.html
摘要:微服務架構(gòu)著重培養(yǎng)通用可重用的服務。服務注冊和發(fā)現(xiàn)微服務架構(gòu)下,有大量的微服務需要處理。網(wǎng)關也是獲得微服務狀態(tài)監(jiān)控信息的中心。實際情況是,微服務和其它企業(yè)架構(gòu)并存。 引言:上篇文章介紹了微服務和單體架構(gòu)的區(qū)別、微服務的設計、消息、服務間通信、數(shù)據(jù)去中心化,本篇會繼續(xù)深入微服務,介紹其它特性。 治理去中心化 通常治理的意思是構(gòu)建方案,并且迫使人們通過努力達到組織的目標。SOA治理指導開發(fā)...
摘要:微服務架構(gòu)著重培養(yǎng)通用可重用的服務。服務注冊和發(fā)現(xiàn)微服務架構(gòu)下,有大量的微服務需要處理。網(wǎng)關也是獲得微服務狀態(tài)監(jiān)控信息的中心。實際情況是,微服務和其它企業(yè)架構(gòu)并存。 引言:上篇文章介紹了微服務和單體架構(gòu)的區(qū)別、微服務的設計、消息、服務間通信、數(shù)據(jù)去中心化,本篇會繼續(xù)深入微服務,介紹其它特性。 治理去中心化 通常治理的意思是構(gòu)建方案,并且迫使人們通過努力達到組織的目標。SOA治理指導開發(fā)...
摘要:微服務架構(gòu)著重培養(yǎng)通用可重用的服務。服務注冊和發(fā)現(xiàn)微服務架構(gòu)下,有大量的微服務需要處理。網(wǎng)關也是獲得微服務狀態(tài)監(jiān)控信息的中心。實際情況是,微服務和其它企業(yè)架構(gòu)并存。 引言:上篇文章介紹了微服務和單體架構(gòu)的區(qū)別、微服務的設計、消息、服務間通信、數(shù)據(jù)去中心化,本篇會繼續(xù)深入微服務,介紹其它特性。 治理去中心化 通常治理的意思是構(gòu)建方案,并且迫使人們通過努力達到組織的目標。SOA治理指導開發(fā)...
摘要:框架具有輕便,開源的優(yōu)點,所以本譯見構(gòu)建用戶管理微服務五使用令牌和來實現(xiàn)身份驗證往期譯見系列文章在賬號分享中持續(xù)連載,敬請查看在往期譯見系列的文章中,我們已經(jīng)建立了業(yè)務邏輯數(shù)據(jù)訪問層和前端控制器但是忽略了對身份進行驗證。 重拾后端之Spring Boot(四):使用JWT和Spring Security保護REST API 重拾后端之Spring Boot(一):REST API的搭建...
閱讀 1348·2023-04-26 03:05
閱讀 802·2021-10-19 11:43
閱讀 3278·2021-09-26 09:55
閱讀 851·2019-08-30 15:56
閱讀 1013·2019-08-30 15:44
閱讀 1273·2019-08-30 15:44
閱讀 2750·2019-08-30 14:23
閱讀 3263·2019-08-30 13:13