整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          api文檔自動生成工具

          api文檔自動生成工具

          pi-doc

          java開發,根據代碼自動生成api接口文檔工具,支持RESTful風格

          預覽

          基本信息

          演示

          數據模擬mock

          在線預覽地址

          http://lovepeng.gitee.io/apidoc

          開發原理

          這個工具是一個典型的前后端分離開發的項目,想了解前后端分離開發的同學也可以下載本項目學習。

          項目后端使用java代碼,前端使用angular開發。Java開發時,使用注解把文檔相關信息標注在類的方法上,通過工具自動掃描代碼的注解,生成json數據,發給前端,前端angular解析生成頁面

          本項目自帶一個spring-boot框架為基礎的demo(這里使用spring-boot做演示的demo僅僅是為了方便,本質上只要是java寫的項目都可以用該工具),前端用angular做了一個比較漂亮的界面(最終前端界面都編譯成了html,如果你前端不熟悉,可以跳過,不用管他),這里使用angular開發僅僅是我比較喜歡,你可以用任何你喜歡的的前端框架或者僅僅使用html寫一個漂亮的界面就可以。

          后端項目開源地址:https://github.com/liepeng328/api-doc

          前端開源地址:https://github.com/liepeng328/api-doc-angular

          功能目錄對應關系

          請求參數和響應參數對應

          快速啟動

          當成一個工具類用就可以了,下載本項目,拷貝包com.apidoc下的代碼到你的系統,

          然后拷貝前端html頁面,在static.apidoc文件下,到你的資源文件下。即可使用

          使用時,后臺提供兩個接口,目錄文檔接口和某個功能的詳細接口

          //生成目錄接口ApiDoc apiDoc=new GeneratorApiDoc()
           .setInfo(//設置文檔基本信息
           new ApiDocInfo()
           .setTitle("某莫系統后臺管理文檔")
           .setVersion("1.0")
           .setDescription("")
           )
           .generator(packageName);//指定生成哪個包下controller的文檔
          System.err.println(JsonUtil.toString(detail));//詳細功能接口ApiDocAction detail=new GeneratorApiDoc() //設置數據庫連接信息,可忽略
           .setDriver(driver)
           .setUrl(url)
           .setUserName(userName)
           .setPassword(password)
           .setDataBaseName(dataBaseName)
           .getApiOfMethod(methodUUID);
           System.err.println(JsonUtil.toString(detail));

          一個詳細的例子

          一個詳細例子如下代碼,這里是springboot/springmvc的controller示例(展示兩個文檔,前端接口和后臺接口)參考代碼這個類 UserController.java

          注解詳細介紹

          共有6個注解,標注出整個文檔信息(我為什么講那么詳細,那么啰嗦,而且我沒有把這個項目打成jar包直接給別人使用,就是因為文檔生成最大可能是需要特殊定制,確保你拿到該代碼可以個性化定制功能,隨意修改)。

          • Api 標注文檔的功能模塊

          • ApiAction 標注一個功能

          • ApiReqAparams 請求參數

          • ApiResqAparams 響應參數

          • ApiParam 參數,用以組成請求參數和響應參數

          • Table 用以標注實體類(比如bean)和數據庫表的關系,自動從數據庫讀取相關信息,不用寫大量的 ApiReqAparams和ApiResqAparams

          詳細介紹如下

          Api:寫在類上,表明一個功能模塊。

          屬性:

          • name 模塊名稱

          • mapping url映射

          ApiAction: 寫在方法上,表明一個功能點

          屬性:

          • name 方法的功能名稱

          • mapping url映射

          • description 描述

          • method 請求方式(get,post,put,delete)

          ApiReqParams: 請求參數

          屬性:

          • type:參數類型

          • header 在請求頭

          • url 在url后拼接

          • form 表單數據

          • json json格式

          • ApiParam :參數列表

          • value : class類,增加該類可自動讀取數據庫信息,避免寫多個屬性

          • remove: 配合value使用,去除class類中無用的屬性,比如id

          • dataType: 數據類型(字符串string,數字number,文件file,日期date,對象object,數組array,布爾類型boolean)

          • descrption:描述

          • defaultValue: 默認值

          • required:是否必須

          • object:從屬于哪個對象(因為請求參數或者響應參數可能是對象中嵌套對象的,這里為了更好的表示這種層級關系,增加兩個屬性,object和belongTo,構建一個樹結構,表示對象之間無限、互相嵌套)

          • belognTo : 對應object 默認值為"0",字符串0

          ApiRespParams: 響應參數

          屬性:

          • ApiParam: 該參數等同于請求參數中的ApiParam,參考如上描述

          下載本項目并運行

          配置jdk8以上版本,下載代碼,運行ApidocApplication類main方法即可。

          然后訪問地址 http://localhost:8080/index.html

          感謝列表

          該項目為maven項目,引用工具請查看 pom.xml

          感謝 spring-boot

          感謝@路曉磊 的工具類hutool https://gitee.com/loolly/hutool

          感謝阿里fastjson

          譯:h4d35

          預估稿費:120RMB

          投稿方式:發送郵件至linwei#360.cn,或登陸網頁版在線投稿

          前言


          本篇文章主要介紹了在一次漏洞懸賞項目中如何利用配置錯誤挖到一個認證繞過漏洞。

          從JS文件中發現認證繞過漏洞


          本文內容源自一個私有漏洞賞金計劃。在這個漏洞計劃中,接受的漏洞范圍限于目標網站少數幾個公開的功能?;谇捌诎l現的問題(當我被邀請進這個計劃時,其他人一共提交了5個漏洞),似乎很難再挖到新的漏洞。同時,在賞金詳情中提到了這樣一句話:

          如果你成功進入管理頁面,請立即報告,請勿在/admin中進行進一步的測試。

          然而,目標網站中存在一個僅限于未認證和未經授權的用戶訪問的管理頁面。當我們訪問/login或/admin時會跳轉到https://bountysite.com/admin/dashboard?redirect=/。

          對登錄頁面進行暴力破解也許是一個可行方案,但是我并不喜歡這種方式。看一下網頁源碼,沒什么有用的內容。于是我開始查看目標網站的結構。似乎目標網站的JS文件都放在少數幾個文件夾中,如/lib、/js、/application等。

          有意思!

          祭出神器BurpSuite,使用Intruder跑一下看能否在上述文件夾中找到任何可訪問的JS文件。將攻擊點設置為https://bountysite.com/admin/dashboard/js/*attack*.js。注意,不要忘記.js擴展名,這樣如果文件能夠訪問則返回200響應。確實有意思!因為我找到了一些可訪問的JS文件,其中一個文件是/login.js。

          訪問這個JS文件https://bountysite.com/admin/dashboard/js/login.js,請求被重定向至管理頁面:) 。但是,我并沒有查看該文件的權限,只能看到部分接口信息。

          但是我并沒有就此止步。這看起來很奇怪,為什么我訪問一個.js文件卻被作為HTML加載了呢?經過一番探查,終于發現,我能夠訪問管理頁面的原因在于*login*。是的,只要在請求路徑/dashboard/后的字符串中含有*login*(除了'login',這只會使我回到登錄頁面),請求就會跳轉到這個管理接口,但是卻沒有正確的授權。

          我繼續對這個受限的管理接口進行了進一步的測試。再一次查看了頁面源碼,試著搞清楚網站結構。在這個管理接口中,有其他一些JS文件能夠幫助我理解管理員是如何執行操作的。一些管理操作需要一個有效的令牌。我試著使用從一個JS文件中泄露的令牌執行相關管理操作,然并卵。請求還是被重定向到了登錄頁面。我發現另外一個真實存在的路徑中也部署了一些內容,那就是/dashboard/controllers/*.php。

          再一次祭出BurpSuite,使用Intruder檢查一下是否存在可以從此處訪問的其他任何路徑。第二次Intruder的結果是,我發現幾乎不存在其他無需授權即可訪問的路徑。這是基于服務器返回的500或者200響應得出的結論。

          回到我在上一步偵察中了解到的網站結構中,我發現這些路徑是在/controllers中定義的,通過/dashboard/*here*/進行訪問。但是直接訪問這些路徑會跳轉到登錄頁面,似乎網站對Session檢查得還挺嚴格。此時我又累又困,幾乎都打算放棄了,但是我想最后再試一把。如果我利用與訪問管理頁面相同的方法去執行這些管理操作會怎么樣呢?很有趣,高潮來了:) 我能夠做到這一點。

          通過訪問/dashboard/photography/loginx,請求跳轉到了Admin Photography頁面,并且擁有完整的權限!

          從這里開始,我能夠執行和訪問/dashboard/*路徑下的所有操作和目錄,這些地方充滿了諸如SQL注入、XSS、文件上傳、公開重定向等漏洞。但是,我沒有繼續深入測試,因為這些都不在賞金計劃之內,根據計劃要求,一旦突破管理授權限制,應立即報告問題。此外,根據管理頁面顯示的調試錯誤信息可知,我之所以能夠訪問到管理頁面,是因為應用程序在/dashboard/controllers/*文件中存在錯誤配置。期望達到的效果是:只要請求鏈接中出現*login*,就重定向至主登錄頁面,然而,實際情況并不如人所愿。

          后記


          總之,這是有趣的一天!我拿到了這個漏洞賞金計劃最大金額的獎勵。

          前言
          一、接口用戶上下文的構建、使用、清除
          ??1. 利用Filter攔截到每一個請求
          ??2. 獲取當前請求的線程
          ??3. 用戶上下文生命周期管理
          ??4. 用戶上下文的使用
          ??5. 用戶上下文的刪除
          二. 用戶登錄&認證

          前言

          作為一名從業已達六年的老碼農,我的工作主要是開發后端Java業務系統,包括各種管理后臺和小程序等。在這些項目中,我設計過單/多租戶體系系統,對接過許多開放平臺,也搞過消息中心這類較為復雜的應用,但幸運的是,我至今還沒有遇到過線上系統由于代碼崩潰導致資損的情況。這其中的原因有三點:一是業務系統本身并不復雜;二是我一直遵循某大廠代碼規約,在開發過程中盡可能按規約編寫代碼;三是經過多年的開發經驗積累,我成為了一名熟練工,掌握了一些實用的技巧。

          考慮到文字太過寡淡,我先上一張圖

          在Spring Boot中,默認情況下,每個請求到達時都會分配一個單獨的線程來處理,而且請求的發起人也不一定都是同一個人,所以一個請求對應一個用戶上下文,并且要求線程隔離,即不同線程的用戶上下文互不影響,最后用戶上下文還需要隨著線程的結束而刪除。
          本文我會從用戶上下文如何構建、如何使用、如何刪除這三個方面解釋接口用戶上下文的設計與實現。

          一、接口用戶上下文的構建、使用、清除

          1. 利用Filter攔截到每一個請求

          由于接口散落在各個Controller中,且絕大部分接口都是需要這個用戶上下文的(注:也不排除不需要用戶上下文的接口存在),所以這里需要統一入口進行創建、銷毀??雌饋砜梢允褂肁OP的方式來實現,
          不過這里有一個更合適的方案,利用SpringBoot自帶的Filter【javax.servlet.Filter】來實現。

          實現起來非常簡單,我這邊自定義了一個WebFilter,代碼如下:

          WebFilter.java

          package com.summo.filter;
          
          import java.io.IOException;
          
          import javax.servlet.Filter;
          import javax.servlet.FilterChain;
          import javax.servlet.FilterConfig;
          import javax.servlet.ServletException;
          import javax.servlet.ServletRequest;
          import javax.servlet.ServletResponse;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          
          import com.summo.context.GlobalUserContext;
          import com.summo.context.UserContext;
          import lombok.extern.slf4j.Slf4j;
          import org.slf4j.MDC;
          import org.springframework.stereotype.Component;
          
          @Slf4j
          @Component
          public class WebFilter implements Filter {
          
              @Override
              public void init(FilterConfig filterConfig) throws ServletException {
                  Filter.super.init(filterConfig);
              }
          
              @Override
              public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
                  throws IOException, ServletException {
                  try {
                      //獲取本次接口的唯一碼
                      String token=java.util.UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
                      MDC.put("requestId", token);
                      //獲取請求頭
                      HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequest;
                      HttpServletResponse httpServletResponse=(HttpServletResponse)servletResponse;
                      log.info("當前請求鏈接為:[{}]", httpServletRequest.getRequestURL());
                      //設置用戶上下文
                      UserContext userContext=new UserContext();
                      userContext.setUserId(1L);
                      GlobalUserContext.setUserContext(userContext);
                      //執行doFilter,這行一定要加,否則程序會中斷掉
                      filterChain.doFilter(httpServletRequest, httpServletResponse);
                  } catch (Exception e) {
                      log.error("do doFilter exception", e);
                  } finally {
                      GlobalUserContext.clear();
                      MDC.remove("requestId");
                  }
              }
          
              @Override
              public void destroy() {
                  Filter.super.destroy();
              }
          }
          

          這段代碼的核心方法是:public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
          我們可以在這個方法里面獲取到ServletRequest和ServletResponse,這兩個類能獲取到代表著我們可以操作整個請求過程,這里如何確定當前請求的用戶?下面有一張流程圖供大家參考:

          還有一種做法是使用JWT來當做用戶token,因為JWT本身就可以存儲一些信息,所以我們就不需要去緩存用戶信息了,直接解析JWT即可,這種做法在分布式應用中很常見。

          2. 獲取當前請求的線程

          上面已經獲取到用戶信息了,現在需要將用戶信息放入用戶上下文中,但由于請求的發起人不一定都是同一個人,所以一個請求對應著一個用戶上下文,也即一個線程設置一個上下文。那么這里就需要獲取到當前線程才能設置上下文。

          獲取當前線程有很多辦法,這里推薦使用阿里巴巴開源的TTL框架(TransmittableThreadLocal)來實現,功能強大且用法簡單。

          引入方法如下:

          <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>transmittable-thread-local</artifactId>
            <version>2.11.1</version>
          </dependency>
          

          使用方法如下:

           private static final TransmittableThreadLocal<UserContext> USER_HOLDER=new TransmittableThreadLocal<>();
          

          直接new一個對象就行,而且支持泛型。

          3. 用戶上下文生命周期管理

          對于用戶上下文的生命周期管理需要定義3個方法:

          • 設置上下文用戶信息;
          • 獲取上下文用戶信息
          • 清除上下文用戶信息

          以上方法均為靜態方法。

          下面是一個簡單的例子:
          GlobalUserContext.java

          package com.summo.context;
          
          import com.alibaba.ttl.TransmittableThreadLocal;
          
          public class GlobalUserContext {
          
              private static final TransmittableThreadLocal<UserContext> USER_HOLDER=new TransmittableThreadLocal<>();
          
              /**
               * 設置上下文用戶信息
               *
               * @param user 用戶信息
               */
              public static void setUserContext(UserContext user) {
                  USER_HOLDER.set(user);
              }
          
              /**
               * 獲取上下文用戶信息
               */
              public static UserContext getUserContext() {
                  return USER_HOLDER.get();
              }
          
              /**
               * 清除上下文用戶信息
               */
              public static void clear() {
                  USER_HOLDER.remove();
              }
          }
          

          UserContext.java

          package com.summo.context;
          
          import lombok.Data;
          
          @Data
          public class UserContext {
          
              /**
               * 用戶ID
               */
              private Long userId;
          
          }
          

          調用方式如下:

          設置上下文用戶信息:GlobalUserContext.setUserContext(userContext);
          獲取上下文用戶信息:GlobalUserContext.getUserContext();
          清除上下文用戶信息:GlobalUserContext.clear();

          4. 用戶上下文的使用

          獲取用戶上下文很方便,調用GlobalUserContext.getUserContext();就行了,這里我主要講一下用戶上下文的使用場景。

          a. 身份認證

          可以將用戶的身份認證信息(如用戶名、密碼、權限等)保存在用戶上下文中,在需要進行鑒權的地方進行驗證。

          b. 用戶日志記錄

          正如《優化接口設計的思路》系列:第三篇—在用戶使用系統過程中留下痕跡 的方法三.

          c. 防止接口數據越權

          舉個例子,比如有些業務需要獲取當前登錄用戶的信息、當前登錄用戶的收藏、當前登錄用戶的瀏覽記錄,這樣的接口總不能在接口上傳一個userId吧?真要這樣干了,非得給安全罵死。。。
          利用用戶上下文的話,接口就可以不用傳遞任何參數獲取到當前用戶的userId,實現你的需求啦。

          d. 跨服務調用

          在分布式系統中,可以將用戶上下文信息傳遞給其他服務,以保持用戶的一致性和連貫性。

          e. 監控和統計

          可以將用戶上下文中的信息用于系統的監控和統計,如請求的處理時間、請求的次數等。

          5. 用戶上下文的刪除

          刪除很簡單,調用GlobalUserContext.clear();即可,詳情可見WebFilter.java內容。

          二. 用戶登錄&認證

          上面主要是說怎么獲取到接口請求的用戶以及怎么設置用戶上下文,但沒說用戶身份是什么時候確認的以及怎么確認的,這里說一下常見做法。
          想要確認用戶信息就不得不提到用戶登錄&認證這套東西了,登錄的方式非常多,簡單的有賬號密碼登錄、手機驗證碼登錄,復雜的就是單點登錄、三方授權登錄如微信掃碼、支付寶掃碼等。雖然方式多,但是結果都一樣的:
          確認當前用戶身份。

          當前用戶身份確認好之后,系統一般會根據當前用戶信息生成一個唯一的并帶有時效性的token,放入下一次請求的cookie中。等到下一次請求來的時候,我們就可以從cookie中獲取這個token,利用這個token獲取這個用戶的信息。

          由于用戶認證情況太多,這里我就不貼代碼了,上面是賬號密碼登錄用戶認證的的時序圖,供大家參考。

          作者:sum墨

          原文鏈接:https://www.cnblogs.com/wlovet/p/17671747.html


          主站蜘蛛池模板: 国产一区玩具在线观看| 成人无码精品一区二区三区| 亚欧成人中文字幕一区| 狠狠综合久久av一区二区| 久久精品一区二区三区资源网 | 夜夜添无码一区二区三区| 人妻免费一区二区三区最新| 精品国产日韩亚洲一区在线| 天堂资源中文最新版在线一区| 亚洲av日韩综合一区久热| 亚洲乱码国产一区三区| 冲田杏梨高清无一区二区| 在线免费视频一区| 一区二区三区高清| 亚洲国产一区在线观看| 无码精品一区二区三区在线| 亚洲V无码一区二区三区四区观看| 99久久精品国产高清一区二区| 精品视频一区二区三区在线播放| 日本一区二三区好的精华液| 午夜天堂一区人妻| 性无码一区二区三区在线观看| 日韩av片无码一区二区不卡电影| 久久免费区一区二区三波多野| 免费一区二区三区| 亲子乱AV视频一区二区| 精品人妻少妇一区二区三区在线| 日本片免费观看一区二区| 久久se精品一区二区国产| 麻豆天美国产一区在线播放| 久久国产精品视频一区| 亚洲一区中文字幕在线观看| 高清一区二区三区免费视频| 色老板在线视频一区二区| 一区二区三区视频在线观看| 无码成人一区二区| 人妻互换精品一区二区| 波多野结衣中文一区| 中文字幕精品一区| 亚洲午夜电影一区二区三区| 国产一区二区在线观看麻豆|