chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SpringBoot 后端接口規(guī)范(下)

jf_78858299 ? 來(lái)源:架構(gòu)師 ? 作者:架構(gòu)師 ? 2023-05-05 17:02 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

七、接口版本控制

1、簡(jiǎn)介

SpringBoot項(xiàng)目中,如果要進(jìn)行restful接口的版本控制一般有以下幾個(gè)方向:

  • 基于path的版本控制
  • 基于header的版本控制

在spring MVC下,url映射到哪個(gè)method是由RequestMappingHandlerMapping來(lái)控制的,那么我們也是通過(guò)RequestMappingHandlerMapping來(lái)做版本控制的。

2、Path控制實(shí)現(xiàn)

首先定義一個(gè)注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiVersion {
    // 默認(rèn)接口版本號(hào)1.0開(kāi)始,這里我只做了兩級(jí),多級(jí)可在正則進(jìn)行控制
    String value() default "1.0";
}

ApiVersionCondition用來(lái)控制當(dāng)前request 指向哪個(gè)method

public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {
    private static final Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\\\d+\\\\.\\\\d+)");

    private final String version;

    public ApiVersionCondition(String version) {
        this.version = version;
    }

    @Override
    public ApiVersionCondition combine(ApiVersionCondition other) {
        // 采用最后定義優(yōu)先原則,則方法上的定義覆蓋類(lèi)上面的定義
        return new ApiVersionCondition(other.getApiVersion());
    }

    @Override
    public ApiVersionCondition getMatchingCondition(HttpServletRequest httpServletRequest) {
        Matcher m = VERSION_PREFIX_PATTERN.matcher(httpServletRequest.getRequestURI());
        if (m.find()) {
            String pathVersion = m.group(1);
            // 這個(gè)方法是精確匹配
            if (Objects.equals(pathVersion, version)) {
                return this;
            }
            // 該方法是只要大于等于最低接口version即匹配成功,需要和compareTo()配合
            // 舉例:定義有1.0/1.1接口,訪問(wèn)1.2,則實(shí)際訪問(wèn)的是1.1,如果從小開(kāi)始那么排序反轉(zhuǎn)即可
//            if(Float.parseFloat(pathVersion)>=Float.parseFloat(version)){
//                return this;
//            }

        }
        return null;
    }

    @Override
    public int compareTo(ApiVersionCondition other, HttpServletRequest request) {
        return 0;
        // 優(yōu)先匹配最新的版本號(hào),和getMatchingCondition注釋掉的代碼同步使用
//        return other.getApiVersion().compareTo(this.version);
    }

    public String getApiVersion() {
        return version;
    }

}

PathVersionHandlerMapping用于注入spring用來(lái)管理

public class PathVersionHandlerMapping extends RequestMappingHandlerMapping {

    @Override
    protected boolean isHandler(Class? beanType) {
        return AnnotatedElementUtils.hasAnnotation(beanType, Controller.class);
    }

    @Override
    protected RequestCondition? getCustomTypeCondition(Class? handlerType) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType,ApiVersion.class);
        return createCondition(apiVersion);
    }

    @Override
    protected RequestCondition? getCustomMethodCondition(Method method) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(method,ApiVersion.class);
        return createCondition(apiVersion);
    }

    private RequestCondition

WebMvcConfiguration配置類(lèi)讓spring來(lái)接管

@Configuration
public class WebMvcConfiguration implements WebMvcRegistrations {

    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new PathVersionHandlerMapping();
    }
}

最后controller進(jìn)行測(cè)試,默認(rèn)是v1.0,如果方法上有注解,以方法上的為準(zhǔn)(該方法vx.x在路徑任意位置出現(xiàn)都可解析)

@RestController
@ApiVersion
@RequestMapping(value = "/{version}/test")
public class TestController {

    @GetMapping(value = "one")
    public String query(){
        return "test api default";
    }

    @GetMapping(value = "one")
    @ApiVersion("1.1")
    public String query2(){
        return "test api v1.1";
    }


    @GetMapping(value = "one")
    @ApiVersion("3.1")
    public String query3(){
        return "test api v3.1";
    }
}

3、header控制實(shí)現(xiàn)

總體原理與Path類(lèi)似,修改ApiVersionCondition即可,之后訪問(wèn)時(shí)在header帶上X-VERSION參數(shù)即可

public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {
    private static final String X_VERSION = "X-VERSION";
    private final String version ;
    
    public ApiVersionCondition(String version) {
        this.version = version;
    }

    @Override
    public ApiVersionCondition combine(ApiVersionCondition other) {
        // 采用最后定義優(yōu)先原則,則方法上的定義覆蓋類(lèi)上面的定義
        return new ApiVersionCondition(other.getApiVersion());
    }

    @Override
    public ApiVersionCondition getMatchingCondition(HttpServletRequest httpServletRequest) {
        String headerVersion = httpServletRequest.getHeader(X_VERSION);
        if(Objects.equals(version,headerVersion)){
            return this;
        }
        return null;
    }

    @Override
    public int compareTo(ApiVersionCondition apiVersionCondition, HttpServletRequest httpServletRequest) {
        return 0;
    }
    public String getApiVersion() {
        return version;
    }

}

八、API接口安全

1、簡(jiǎn)介

APP、前后端分離項(xiàng)目都采用[API]接口形式與服務(wù)器進(jìn)行數(shù)據(jù)通信,傳輸?shù)臄?shù)據(jù)被偷窺、被抓包、被偽造時(shí)有發(fā)生,那么如何設(shè)計(jì)一套比較安全的API接口方案至關(guān)重要,一般的解決方案有以下幾點(diǎn):

  • Token授權(quán)認(rèn)證,防止未授權(quán)用戶(hù)獲取數(shù)據(jù);
  • 時(shí)間戳超時(shí)機(jī)制;
  • URL簽名,防止請(qǐng)求參數(shù)被篡改;
  • 防重放,防止接口被第二次請(qǐng)求,防采集;
  • 采用HTTPS通信協(xié)議,防止數(shù)據(jù)明文傳輸;

2、Token授權(quán)認(rèn)證

因?yàn)镠TTP協(xié)議是無(wú)狀態(tài)的,Token的設(shè)計(jì)方案是用戶(hù)在客戶(hù)端使用用戶(hù)名和密碼登錄后,服務(wù)器會(huì)給客戶(hù)端返回一個(gè)Token,并將Token以鍵值對(duì)的形式存放在緩存(一般是Redis)中,后續(xù)客戶(hù)端對(duì)需要授權(quán)模塊的所有操作都要帶上這個(gè)Token,服務(wù)器端接收到請(qǐng)求后進(jìn)行Token驗(yàn)證,如果Token存在,說(shuō)明是授權(quán)的請(qǐng)求。

Token生成的設(shè)計(jì)要求

  • 應(yīng)用內(nèi)一定要唯一,否則會(huì)出現(xiàn)授權(quán)混亂,A用戶(hù)看到了B用戶(hù)的數(shù)據(jù);
  • 每次生成的[Token]一定要不一樣,防止被記錄,授權(quán)永久有效;
  • 一般Token對(duì)應(yīng)的是Redis的key,value存放的是這個(gè)用戶(hù)相關(guān)緩存信息,比如:用戶(hù)的id;
  • 要設(shè)置Token的過(guò)期時(shí)間,過(guò)期后需要客戶(hù)端重新登錄,獲取新的Token,如果[Token]有效期設(shè)置較短,會(huì)反復(fù)需要用戶(hù)登錄,體驗(yàn)比較差,我們一般采用Token過(guò)期后,客戶(hù)端靜默登錄的方式,當(dāng)客戶(hù)端收到[Token]過(guò)期后,客戶(hù)端用本地保存的用戶(hù)名和密碼在后臺(tái)靜默登錄來(lái)獲取新的[Token],還有一種是單獨(dú)出一個(gè)刷新Token的接口,但是一定要注意刷新機(jī)制和安全問(wèn)題;

根據(jù)上面的設(shè)計(jì)方案要求,我們很容易得到Token=md5(用戶(hù)ID+登錄的時(shí)間戳+服務(wù)器端秘鑰)這種方式來(lái)獲得Token,因?yàn)橛脩?hù)ID是應(yīng)用內(nèi)唯一的,登錄的時(shí)間戳保證每次登錄的時(shí)候都不一樣,服務(wù)器端秘鑰是配置在服務(wù)器端參與加密的字符串(即:鹽),目的是提高Token加密的破解難度,注意一定不要泄漏

3、時(shí)間戳超時(shí)機(jī)制

客戶(hù)端每次請(qǐng)求接口都帶上當(dāng)前時(shí)間的時(shí)間戳timestamp,服務(wù)端接收到timestamp后跟當(dāng)前時(shí)間進(jìn)行比對(duì),如果時(shí)間差大于一定時(shí)間(比如:1分鐘),則認(rèn)為該請(qǐng)求失效。 時(shí)間戳超時(shí)機(jī)制是防御DOS攻擊的有效手段。 例如http://url/getInfo?id=1&timetamp=1661061696

4、URL簽名

寫(xiě)過(guò)支付寶或微信支付對(duì)接的同學(xué)肯定對(duì)URL簽名不陌生,我們只需要將原本發(fā)送給server端的明文參數(shù)做一下簽名,然后在server端用相同的算法再做一次簽名,對(duì)比兩次簽名就可以確保對(duì)應(yīng)明文的參數(shù)有沒(méi)有被中間人篡改過(guò)。例如http://url/getInfo?id=1&timetamp=1559396263&sign=e10adc3949ba59abbe56e057f20f883e

簽名算法過(guò)程

  • 首先對(duì)通信的參數(shù)按key進(jìn)行字母排序放入數(shù)組中(一般請(qǐng)求的接口地址也要參與排序和簽名,那么需要額外添加url=http://url/getInfo這個(gè)參數(shù))
  • 對(duì)排序完的數(shù)組鍵值對(duì)用&進(jìn)行連接,形成用于加密的參數(shù)字符串
  • 在加密的參數(shù)字符串前面或者后面加上私鑰,然后用md5進(jìn)行加密,得到sign,然后隨著請(qǐng)求接口一起傳給服務(wù)器。服務(wù)器端接收到請(qǐng)求后,用同樣的算法獲得服務(wù)器的sign,對(duì)比客戶(hù)端的sign是否一致,如果一致請(qǐng)求有效

5、防重放

客戶(hù)端第一次訪問(wèn)時(shí),將簽名sign存放到服務(wù)器的Redis中,超時(shí)時(shí)間設(shè)定為跟時(shí)間戳的超時(shí)時(shí)間一致,二者時(shí)間一致可以保證無(wú)論在timestamp限定時(shí)間內(nèi)還是外 URL都只能訪問(wèn)一次,如果被非法者截獲,使用同一個(gè)URL再次訪問(wèn),如果發(fā)現(xiàn)緩存服務(wù)器中已經(jīng)存在了本次簽名,則拒絕服務(wù)。

如果在緩存中的簽名失效的情況下,有人使用同一個(gè)URL再次訪問(wèn),則會(huì)被時(shí)間戳超時(shí)機(jī)制攔截,這就是為什么要求sign的超時(shí)時(shí)間要設(shè)定為跟時(shí)間戳的超時(shí)時(shí)間一致。拒絕重復(fù)調(diào)用機(jī)制確保URL被別人截獲了也無(wú)法使用(如抓取數(shù)據(jù))

方案流程

  • 客戶(hù)端通過(guò)用戶(hù)名密碼登錄服務(wù)器并獲取Token;
  • 客戶(hù)端生成時(shí)間戳timestamp,并將timestamp作為其中一個(gè)參數(shù);
  • 客戶(hù)端將所有的參數(shù),包括Token和timestamp按照自己的簽名算法進(jìn)行排序加密得到簽名sign
  • 將token、timestamp和sign作為請(qǐng)求時(shí)必須攜帶的參數(shù)加在每個(gè)請(qǐng)求的URL后邊,例:http://url/request?token=h40adc3949bafjhbbe56e027f20f583a&timetamp=1559396263&sign=e10adc3949ba59abbe56e057f20f883e
  • 服務(wù)端對(duì)token、timestamp和sign進(jìn)行驗(yàn)證,只有在token有效、timestamp未超時(shí)、緩存服務(wù)器中不存在sign三種情況同時(shí)滿足,本次請(qǐng)求才有效;

6、采用HTTPS通信協(xié)議

安全套接字層超文本傳輸協(xié)議HTTPS,為了數(shù)據(jù)傳輸?shù)陌踩琀TTPS在HTTP的基礎(chǔ)上加入了SSL協(xié)議,SSL依靠證書(shū)來(lái)驗(yàn)證服務(wù)器的身份,并為客戶(hù)端和服務(wù)器之間的通信加密。

HTTPS也不是絕對(duì)安全的,比如中間人劫持攻擊,中間人可以獲取到客戶(hù)端與服務(wù)器之間所有的通信內(nèi)容

九、總結(jié)

自此整個(gè)后端接口基本體系就構(gòu)建完畢了

  • 通過(guò)Validator + 自動(dòng)拋出異常來(lái)完成了方便的參數(shù)校驗(yàn)
  • 通過(guò)全局異常處理 + 自定義異常完成了異常操作的規(guī)范
  • 通過(guò)數(shù)據(jù)統(tǒng)一響應(yīng)完成了響應(yīng)數(shù)據(jù)的規(guī)范
  • 多個(gè)方面組裝非常優(yōu)雅的完成了后端接口的協(xié)調(diào),讓開(kāi)發(fā)人員有更多的經(jīng)歷注重業(yè)務(wù)邏輯代碼,輕松構(gòu)建后端接口

這里再說(shuō)幾點(diǎn)

  • controller做好try-catch工作,及時(shí)捕獲異常,可以再次拋出到全局,統(tǒng)一格式返回前端
  • 做好日志系統(tǒng),關(guān)鍵位置一定要有日志
  • 做好全局統(tǒng)一返回類(lèi),整個(gè)項(xiàng)目規(guī)范好定義好
  • controller入?yún)⒆侄慰梢猿橄蟪鲆粋€(gè)公共基類(lèi),在此基礎(chǔ)上進(jìn)行繼承擴(kuò)充
  • controller層做好入?yún)?shù)校驗(yàn)
  • 接口安全驗(yàn)證
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 接口
    +關(guān)注

    關(guān)注

    33

    文章

    9005

    瀏覽量

    153769
  • URL
    URL
    +關(guān)注

    關(guān)注

    0

    文章

    141

    瀏覽量

    15869
  • 后端
    +關(guān)注

    關(guān)注

    0

    文章

    32

    瀏覽量

    2402
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    175

    瀏覽量

    401
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    請(qǐng)問(wèn)可變?cè)鲆娣糯笃鰽D8369后端接模數(shù)轉(zhuǎn)換器AD9268怎么匹配?

    如題,想請(qǐng)教一可變?cè)鲆娣糯笃鰽D8369后端接模數(shù)轉(zhuǎn)換器AD9268怎么匹配?AD9268前接50歐阻抗的手冊(cè)里面有(下圖),可AD8369輸出為200歐阻抗,不知道該怎么接?不知道差分阻抗匹配怎么計(jì)算?@
    發(fā)表于 12-25 11:40

    SpringBoot知識(shí)總結(jié)

    SpringBoot干貨學(xué)習(xí)總結(jié)
    發(fā)表于 08-01 10:40

    怎么學(xué)習(xí)SpringBoot

    SpringBoot學(xué)習(xí)之路(X5)- 整合JPA
    發(fā)表于 06-10 14:52

    怎樣去使用springboot

    怎樣去使用springboot呢?學(xué)習(xí)springboot需要懂得哪些?
    發(fā)表于 10-25 07:13

    SpringBoot應(yīng)用啟動(dòng)運(yùn)行run方法

    什么時(shí)候創(chuàng)建嵌入式的Servlet容器工廠?什么時(shí)候獲取嵌入式的Servlet容器并啟動(dòng)Tomcat;獲取嵌入式的Servlet容器工廠:1)、SpringBoot應(yīng)用啟動(dòng)運(yùn)行run方法2
    發(fā)表于 12-20 06:16

    基于DSP控制的電力線通信模擬前端接口設(shè)計(jì)

    基于DSP控制的電力線通信模擬前端接口設(shè)計(jì)
    發(fā)表于 10-20 15:51 ?5次下載
    基于DSP控制的電力線通信模擬前<b class='flag-5'>端接口</b>設(shè)計(jì)

    數(shù)字接口—單端接口與差動(dòng)接口的對(duì)比

    數(shù)字接口—單端接口與差動(dòng)接口的對(duì)比
    發(fā)表于 11-07 08:07 ?0次下載
    數(shù)字<b class='flag-5'>接口</b>—單<b class='flag-5'>端接口</b>與差動(dòng)<b class='flag-5'>接口</b>的對(duì)比

    什么是 SpringBoot

    本文從為什么要有 `SpringBoot`,以及 `SpringBoot` 到底方便在哪里開(kāi)始入手,逐步分析了 `SpringBoot` 自動(dòng)裝配的原理,最后手寫(xiě)了一個(gè)簡(jiǎn)單的 `start` 組件,通過(guò)實(shí)戰(zhàn)來(lái)體會(huì)了 `
    的頭像 發(fā)表于 04-07 11:28 ?1746次閱讀
    什么是 <b class='flag-5'>SpringBoot</b>?

    SpringBoot的核心注解1

    今天跟大家來(lái)探討SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達(dá)到零配置
    的頭像 發(fā)表于 04-07 14:34 ?953次閱讀
    <b class='flag-5'>SpringBoot</b>的核心注解1

    SpringBoot的核心注解2

    今天跟大家來(lái)探討SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達(dá)到零配置
    的頭像 發(fā)表于 04-07 14:34 ?2215次閱讀
    <b class='flag-5'>SpringBoot</b>的核心注解2

    SpringBoot 后端接口規(guī)范(上)

    一個(gè)后端接口大致分為四個(gè)部分組成: 接口地址(url)、接口請(qǐng)求方式(get、post等)、請(qǐng)求數(shù)據(jù)(request)、響應(yīng)數(shù)據(jù)(response) 。雖然說(shuō)后端接口的編寫(xiě)并沒(méi)有統(tǒng)一
    的頭像 發(fā)表于 05-05 17:00 ?1077次閱讀
    <b class='flag-5'>SpringBoot</b> <b class='flag-5'>后端接口</b><b class='flag-5'>規(guī)范</b>(上)

    SpringBoot 后端接口規(guī)范(中)

    一個(gè)后端接口大致分為四個(gè)部分組成: 接口地址(url)、接口請(qǐng)求方式(get、post等)、請(qǐng)求數(shù)據(jù)(request)、響應(yīng)數(shù)據(jù)(response) 。雖然說(shuō)后端接口的編寫(xiě)并沒(méi)有統(tǒng)一
    的頭像 發(fā)表于 05-05 17:01 ?880次閱讀
    <b class='flag-5'>SpringBoot</b> <b class='flag-5'>后端接口</b><b class='flag-5'>規(guī)范</b>(中)

    后端分離必備的接口規(guī)范

    隨著互聯(lián)網(wǎng)的高速發(fā)展,前端頁(yè)面的展示、交互體驗(yàn)越來(lái)越靈活、炫麗,響應(yīng)體驗(yàn)也要求越來(lái)越高,后端服務(wù)的高并發(fā)、高可用、高性能、高擴(kuò)展等特性的要求也愈加苛刻,從而導(dǎo)致前后端研發(fā)各自專(zhuān)注于自己擅長(zhǎng)的領(lǐng)域深耕細(xì)作。
    的頭像 發(fā)表于 05-15 17:16 ?1148次閱讀
    前<b class='flag-5'>后端</b>分離必備的<b class='flag-5'>接口</b><b class='flag-5'>規(guī)范</b>

    springboot后端交互流程

    Boot 進(jìn)行開(kāi)發(fā)時(shí),前后端交互是一個(gè)非常重要的部分,本文將詳細(xì)介紹 Spring Boot 前后端交互的流程。 前后端交互的基本原理 在前后端交互的過(guò)程中,前端負(fù)責(zé)向
    的頭像 發(fā)表于 11-22 16:00 ?3219次閱讀

    一個(gè)注解搞定SpringBoot接口防刷

    技術(shù)要點(diǎn):springboot的基本知識(shí),redis基本操作,
    的頭像 發(fā)表于 11-28 10:46 ?580次閱讀