摘要:下面舉幾個未經保護的可能將會造成的安全事故通過抓包,找到發送短信驗證碼的。這可能將會直接對用戶造成財產損失。因此,未經安全保護的非常的危險,對進行安全保護異常重要。可以將請求參數一并放入中,以此來確保數據的安全性。
未經安全保護的API非常的危險
未經安全保護的API非常的危險,其和裸奔無異。即使API文檔沒有被人為泄露,通過簡單的抓包也可以非常容易的獲取到API的URL以及對應的請求參數。下面舉幾個未經保護的API可能將會造成的安全事故:
通過抓包,找到發送短信驗證碼的API。然后利用該API惡意的發送短信驗證碼。而發送短信驗證碼是需要收費的,這樣的惡意攻擊,將會導致無故的損失發送短信的費用。還會讓很多不明真相的吃瓜群眾收到奇怪的短信驗證碼,進而對產品產生不好的印象。
通過抓包,找到獲取用戶信息的API。該API的暴露,將會讓該平臺上所有用戶的信息被毫無保留的暴露在互聯網上。如果用戶信息中還涉及到一些重要的個人信息。比如身份證號,手機號等。將會讓用戶受到人生和財產的損失。
通過抓包,找到和財產相關的API。比如說修改訂單狀態的API。一旦該API暴露,黑客可以惡意的修改用戶的訂單狀態。比如說將訂單的狀態修改為取消。這可能將會直接對用戶造成財產損失。
上面這些例子僅僅只是筆者臨時想到的一些利用裸露API進行惡意攻擊的方式,實際中還存在著更多由于未對API進行加密,而造成損失的情況。因此,未經安全保護的API非常的危險,對API進行安全保護異常重要。
什么是JWTJWT是json web token的縮寫。關于其如何確保數據傳輸的安全性的文章你可以在搜索引擎上找到很多,在這里我將僅僅簡單介紹我對此的理解。
JWT可以理解為一串通過特定算法生成的字符串,在API的請求中,將這段字符串放入請求參數中。API Server通過判斷這段字符串是合法的還是偽造的,來確定這次API請求是否有效。通過該安全措施,將確保即使API被暴露,沒有生成JWT字符串的算法,也沒有辦法成功調用API。
JWT字符串分為兩個部分(官方的說法是分為3個部分),分別是‘未加密部分’和‘加密部分’。而‘加密部分’的內容實際上是‘未加密部分’加密得到的。API Server檢查JWT字符串是否有效的第一步是將‘加密部分’解密然后與‘未加密部分’進行比較,查看是否內容一致。如果內容不一致,則說明該JWT字符串是偽造的。
JWT字符串中包括一個‘過期時間’的字段,當API Server獲取到JWT字符串后,可以通過檢查該字段與當前時間相比,是否已經處于過期的狀態。如果‘過期時間’字段早于當前時間,則說明這次API請求是無效的。
你也可以在JWT字段種加入自定義的字段。然后在API Server獲取到JWT字段后,通過這些自定義的字段判斷是不是符合具體的業務邏輯,進而判斷這次請求是不是有效。
利用jjwt實現JWT對API的保護jjwt是java對JWT的封裝,下面的方法將會演示。在java中如何利用jjwt實現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字符串中的數據,并進行最基礎的驗證 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字符串時,如果‘過期時間字段’已經早于當前時間,將會拋出ExpiredJwtException異常,說明本次請求已經失效 catch (SignatureException|ExpiredJwtException e) { return false; } }Client端
Client端需要做的就是,根據API的需求將JWT字符串放入http請求中。我的做法是對于所有的API,在Client端生成JWT字段,然后將其添加到http請求的header中,確保所有的API都獲得保護。對于一些比較敏感的信息,再用加一層JWT驗證。比如說用戶信息,在調用登錄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的權限"; } } @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的權限"; } }補充
JWT在一定程度上,保護了API的安全。但是其本身還是存在一定的缺陷的。比如說,一定JWT的加密密鑰一旦被泄露,那么黑客就可以生成JWT字符串了,因此保護好JWT加密密鑰非常重要。
在上面的例子當中,介紹了獲取用戶信息API需要加入userJwt的例子。userJwt其實就是在JWT字符串中加入了userId字段,繼而保證一個userJwt只能訪問一個用戶的信息。對于其他的API,比如說PUT和POST操作,需要新增和修改數據的API。可以將請求參數一并放入jwt中,以此來確保數據的安全性。否則黑客還可以在JWT字符串還沒有過期的時間段內,修改請求中的參數,達到攻擊的目的。
另外還要防止重復式攻擊,黑客還可以在JWT字符串還沒有過期的時間段內,重復提交請求,達到攻擊的目的。比如說新增訂單的API,如果被黑客采用重復式攻擊的方式,就會生成多個訂單。
參考RESTful Api 身份認證中的安全性設計探討
JSON Web Token - 在Web應用間安全地傳遞信息
八幅漫畫理解使用JSON Web Token設計單點登錄系統
How to Create and verify JWTs in Java
jwt官方介紹
jwt官網
jjwt在github上的地址
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/66104.html
摘要:微服務架構著重培養通用可重用的服務。服務注冊和發現微服務架構下,有大量的微服務需要處理。網關也是獲得微服務狀態監控信息的中心。實際情況是,微服務和其它企業架構并存。 引言:上篇文章介紹了微服務和單體架構的區別、微服務的設計、消息、服務間通信、數據去中心化,本篇會繼續深入微服務,介紹其它特性。 治理去中心化 通常治理的意思是構建方案,并且迫使人們通過努力達到組織的目標。SOA治理指導開發...
摘要:微服務架構著重培養通用可重用的服務。服務注冊和發現微服務架構下,有大量的微服務需要處理。網關也是獲得微服務狀態監控信息的中心。實際情況是,微服務和其它企業架構并存。 引言:上篇文章介紹了微服務和單體架構的區別、微服務的設計、消息、服務間通信、數據去中心化,本篇會繼續深入微服務,介紹其它特性。 治理去中心化 通常治理的意思是構建方案,并且迫使人們通過努力達到組織的目標。SOA治理指導開發...
摘要:微服務架構著重培養通用可重用的服務。服務注冊和發現微服務架構下,有大量的微服務需要處理。網關也是獲得微服務狀態監控信息的中心。實際情況是,微服務和其它企業架構并存。 引言:上篇文章介紹了微服務和單體架構的區別、微服務的設計、消息、服務間通信、數據去中心化,本篇會繼續深入微服務,介紹其它特性。 治理去中心化 通常治理的意思是構建方案,并且迫使人們通過努力達到組織的目標。SOA治理指導開發...
摘要:框架具有輕便,開源的優點,所以本譯見構建用戶管理微服務五使用令牌和來實現身份驗證往期譯見系列文章在賬號分享中持續連載,敬請查看在往期譯見系列的文章中,我們已經建立了業務邏輯數據訪問層和前端控制器但是忽略了對身份進行驗證。 重拾后端之Spring Boot(四):使用JWT和Spring Security保護REST API 重拾后端之Spring Boot(一):REST API的搭建...
閱讀 1323·2023-04-26 03:05
閱讀 781·2021-10-19 11:43
閱讀 3231·2021-09-26 09:55
閱讀 836·2019-08-30 15:56
閱讀 994·2019-08-30 15:44
閱讀 1248·2019-08-30 15:44
閱讀 2728·2019-08-30 14:23
閱讀 3245·2019-08-30 13:13