最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何使用Spring Boot實現(xiàn)接口時間戳鑒權(quán)

 更新時間:2025年06月09日 10:01:41   作者:weixin_43833540  
這篇文章主要為大家詳細介紹了如何使用Spring Boot實現(xiàn)接口時間戳鑒權(quán),文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴要了解下

Spring Boot實現(xiàn)接口時間戳鑒權(quán),簽名(sign)和時間戳(ts)放入請求頭(Header)。

一、請求頭參數(shù)設計

參數(shù)名類型說明
tsLong13位時間戳(Unix毫秒值),必填,標識請求有效期
signString簽名值,必填,用于校驗請求合法性

二、簽名算法調(diào)整(Header版)

1. 構(gòu)造原始字符串

str = key + url_encode(path) + ts

path:請求的URL路徑部分(不含查詢參數(shù)和域名),例如:/api/v1/user。

url_encode(path):需對路徑中的特殊字符進行URL編碼(如中文、/等無需編碼,但空格需轉(zhuǎn)義為%20)。

2. 生成簽名 SIGN

sgin = md5(S).toLowerCase()

結(jié)果轉(zhuǎn)換為小寫字符串,與請求頭中的sign對比校驗。

三、Spring Boot實現(xiàn)流程

1. 創(chuàng)建攔截器(Interceptor)

用于攔截請求,校驗ts和sign的合法性。

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Objects;

public class AuthInterceptor implements HandlerInterceptor {
    private final String secretKey; // 從配置文件獲取密鑰,例如application.properties
    private final long maxClockSkew = 60 * 1000; // 時間窗口:60秒(允許客戶端與服務端的時間誤差)

    public AuthInterceptor(String secretKey) {
        this.secretKey = secretKey;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 1. 校驗時間戳是否存在
        String ts = request.getHeader("ts");
        if (StringUtils.isEmpty(ts)) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.setContentType("application/json");
            // 返回錯誤信息:缺少時間戳
            return false;
        }

        // 2. 校驗時間戳格式及有效性
        long ts;
        try {
            ts = Long.parseLong(ts );
        } catch (NumberFormatException e) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            // 返回錯誤信息:時間戳格式錯誤
            return false;
        }
        long currentTime = System.currentTimeMillis();
        if (currentTime - ts > maxClockSkew|| ts - currentTime > maxClockSkew) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            // 返回錯誤信息:請求已過期
            return false;
        }

        // 3. 校驗簽名是否存在
        String sign= request.getHeader("sign");
        if (StringUtils.isEmpty(sign)) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            // 返回錯誤信息:缺少簽名
            return false;
        }

        // 4. 構(gòu)造原始簽名字符串并生成簽名
        String path = request.getRequestURI(); // 獲取路徑,例如"/api/v1/user"
        String encodedPath = URLEncoder.encode(path, StandardCharsets.UTF_8.toString())
                .replace("+", "%20") // 處理空格編碼差異(URLEncoder默認用+,此處統(tǒng)一為%20)
                .replace("%7E", "~"); // 保留波浪線~的原始格式
        String rawString = secretKey + encodedPath + tsHeader;

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(rawString.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b)); // 轉(zhuǎn)換為小寫16進制字符串
            }
            String generatedSign = sb.toString();

            // 5. 對比簽名
            if (!generatedSign.equals(sign)) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                // 返回錯誤信息:簽名校驗失敗
                return false;
            }
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return false;
        }

        return true; // 校驗通過,允許請求繼續(xù)
    }
}

2. 配置攔截器(WebMvcConfigurer)

將攔截器注冊到Spring Boot的攔截器鏈中,指定需要鑒權(quán)的接口路徑。

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final String secretKey; // 從配置文件獲取密鑰,例如通過@Value注入

    public WebConfig(String secretKey) {
        this.secretKey = secretKey;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        AuthInterceptor authInterceptor = new AuthInterceptor(secretKey);
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/api/v1/**") // 需要鑒權(quán)的接口路徑(如/api/v1下所有接口)
                .excludePathPatterns("/api/v1/public/**"); // 無需鑒權(quán)的公共接口(可選)
    }
}

3. 配置文件(application.properties)

# 密鑰(建議從環(huán)境變量或配置中心獲取,而非硬編碼)
auth.secret-key=your_secret_key_here

四、客戶端請求示例(以Postman為例)

1. 請求頭參數(shù)

名稱
ts1686048000000(當前時間戳,13位Long)
sign計算得到的簽名值(如e10adc3949ba59abbe56e057f20f883e)

2. 簽名計算步驟(JavaScript示例)

function generateSignature(key, path, ts) {
    const encodedPath = encodeURIComponent(path).replace(/[!'()*]/g, encodeURIComponent); // 嚴格編碼特殊字符
    const rawString = key + encodedPath + ts;
    const md5 = require('crypto-js/md5'); // 需要安裝crypto-js庫
    return md5(rawString).toString().toLowerCase();
}

// 示例調(diào)用
const key = 'your_secret_key';
const path = '/api/v1/user'; // 接口路徑
const ts = Date.now(); // 當前時間戳(13位)
const sign = generateSignature(key, path, ts);
console.log(sign); // 輸出簽名值

到此這篇關(guān)于如何使用Spring Boot實現(xiàn)接口時間戳鑒權(quán)的文章就介紹到這了,更多相關(guān)Spring Boot接口時間戳鑒權(quán)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring?Boot?根據(jù)配置決定服務(集群、單機)是否使用某些主件的操作代碼

    Spring?Boot?根據(jù)配置決定服務(集群、單機)是否使用某些主件的操作代碼

    這篇文章主要介紹了Spring?Boot根據(jù)配置決定服務(集群、單機)是否使用某些主件,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-04-04
  • Mybatis中返回主鍵值方式

    Mybatis中返回主鍵值方式

    這篇文章主要介紹了Mybatis中返回主鍵值方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 從面試中的問題分析ThreadLocal

    從面試中的問題分析ThreadLocal

    這篇文章主要介紹了從面試中的問題分析ThreadLocal,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,下面我們來一起學習一下吧
    2019-06-06
  • spring中自動注入注解的實現(xiàn)方式

    spring中自動注入注解的實現(xiàn)方式

    在Spring框架中,AutowiredAnnotationBeanPostProcessor負責處理@Autowired和@Value注解,實現(xiàn)依賴注入,首先通過TypeMappedAnnotations獲取注解,并根據(jù)注解屬性構(gòu)建InjectionMetadata,存入緩存
    2024-09-09
  • Java服務調(diào)用失敗報Service com.oneinfinite.adflow.api.service.TestService未找到的解決方法

    Java服務調(diào)用失敗報Service com.oneinfinite.adflow.api.service.T

    在Java開發(fā)中,服務調(diào)用是常見的操作,尤其是在微服務架構(gòu)中,然而,服務調(diào)用過程中可能會遇到各種問題,下面我們來看看如何解決Service com.oneinfinite.adflow.api.service.TestService with version 0.0.0 not found的問題吧
    2025-03-03
  • mybatis-plus在yml中配置詳解

    mybatis-plus在yml中配置詳解

    本文主要介紹了mybatis-plus在yml中配置詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • Mybatis-Plus動態(tài)表名的實現(xiàn)示例

    Mybatis-Plus動態(tài)表名的實現(xiàn)示例

    面對復雜多變的業(yè)務需求,動態(tài)表名的處理變得愈發(fā)重要,本文主要介紹了Mybatis-Plus動態(tài)表名的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-07-07
  • Java實現(xiàn)五子棋游戲的完整代碼

    Java實現(xiàn)五子棋游戲的完整代碼

    這篇文章主要為大家詳細介紹了Java實現(xiàn)五子棋游戲的完整代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • Java Web十條開發(fā)實用小知識

    Java Web十條開發(fā)實用小知識

    這篇文章主要介紹了Java Web十條開發(fā)實用小知識的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • JavaOOP封裝實例解讀

    JavaOOP封裝實例解讀

    封裝通過private限制屬性訪問,提供get/set方法控制數(shù)據(jù)讀寫,確保值合法,示例中Student類屬性私有,Test類需調(diào)用set方法賦值并驗證,get方法獲取值,實現(xiàn)數(shù)據(jù)隱藏與安全操作
    2025-09-09

最新評論

江安县| 绥芬河市| 通道| 化隆| 大荔县| 余庆县| 梁平县| 葵青区| 安仁县| 南安市| 萝北县| 乐安县| 高碑店市| 永登县| 桂林市| 延长县| 新巴尔虎左旗| 城口县| 军事| 包头市| 长沙县| 余庆县| 泸州市| 道孚县| 宁乡县| 隆回县| 柞水县| 舟曲县| 银川市| 贞丰县| 恩平市| 苍山县| 苏尼特左旗| 永安市| 松原市| 游戏| 资阳市| 蒙城县| 方正县| 甘南县| 岐山县|