欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Boot實(shí)現(xiàn)接口簽名驗(yàn)證的過(guò)程

 更新時(shí)間:2024年04月26日 09:48:05   作者:濤哥是個(gè)大帥比  
在Spring Boot中實(shí)現(xiàn)接口校驗(yàn)簽名通常是為了保證接口請(qǐng)求的安全性和數(shù)據(jù)的完整性,這篇文章主要介紹了Spring Boot實(shí)現(xiàn)接口簽名驗(yàn)證,需要的朋友可以參考下

項(xiàng)目場(chǎng)景:

開(kāi)放接口是指不需要登錄憑證就允許被第三方系統(tǒng)調(diào)用的接口。為了防止開(kāi)放接口被惡意調(diào)用,開(kāi)放接口一般都需要驗(yàn)簽才能被調(diào)用。

在Spring Boot中實(shí)現(xiàn)接口校驗(yàn)簽名通常是為了保證接口請(qǐng)求的安全性和數(shù)據(jù)的完整性。簽名校驗(yàn)通常涉及對(duì)請(qǐng)求參數(shù)的簽名計(jì)算和驗(yàn)證,以確保請(qǐng)求是由可信的發(fā)送方發(fā)送,并且在傳輸過(guò)程中沒(méi)有被篡改。下面,我將詳細(xì)介紹如何在Spring Boot應(yīng)用中實(shí)現(xiàn)接口校驗(yàn)簽名的過(guò)程。

解決方案:

1.配置簽名密鑰

簽名密鑰是用于生成和驗(yàn)證簽名的秘密信息,生成規(guī)則自己定義,需要把生成的密鑰提供給第三方。

比如:

appId:360aa3a3ba074da6a7bb17ae55e72d26
appSecret:81343DC5-6E80-483A-A427-E3DF5FA4E5F3

/**
 * 生成應(yīng)用id和密鑰
 */
@RequestMapping(value = "/getSecret", method = RequestMethod.GET)
public Map<String, String> getSecret() {
	//生成應(yīng)用id和密鑰提供給第三方使用,具體生成規(guī)則自己定
	String appId = UUID.randomUUID().toString().replace("-", "").toLowerCase();
	String appSecret = UUID.randomUUID().toString().toUpperCase();
	System.out.println("appId:"+appId);
	System.out.println("appSecret:"+appSecret);
	Map<String, String> map = new HashMap<>();
	map.put("appId", appId);
	map.put("appSecret", appSecret);
	return map;
}

2.定義簽名算法

一個(gè)用于生成簽名,另一個(gè)用于驗(yàn)證簽名。生成簽名的方法通常將請(qǐng)求參數(shù)按照特定規(guī)則計(jì)算出一個(gè)簽名值。常見(jiàn)的簽名算法有HMAC-SHA1、HMAC-SHA256等。

驗(yàn)證簽名的方法則是對(duì)接收到的請(qǐng)求參數(shù)進(jìn)行同樣的處理,并計(jì)算出一個(gè)簽名值,然后與請(qǐng)求中攜帶的簽名值進(jìn)行比對(duì)。

package com.test.utils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Signature {
    /**
     * 獲取簽名
     * @param secretKey 密鑰
     * @param data  需要簽名的數(shù)據(jù)
     * @return  簽名
     */
    public static String signWithHmacSha1(String secretKey, String data) {
        try {
            SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            return Base64.getEncoder().encodeToString(mac.doFinal(data.getBytes("UTF-8")));
        } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 驗(yàn)證簽名
     * @param secretKey 密鑰
     * @param data  需要簽名的數(shù)據(jù)
     * @param hmac  已經(jīng)簽名的數(shù)據(jù)
     * @return  true:簽名一致
     */
    public static boolean verify(String secretKey, String data, String hmac) {
        String calculatedHmac = signWithHmacSha1(secretKey, data);
        return calculatedHmac.equals(hmac);
    }
}

3.攔截器或過(guò)濾器實(shí)現(xiàn)

使用Spring的攔截器(Interceptor)或過(guò)濾器(Filter)來(lái)實(shí)現(xiàn)對(duì)接口請(qǐng)求的簽名校驗(yàn)。在攔截器或過(guò)濾器中,你可以獲取到請(qǐng)求的參數(shù),并調(diào)用簽名驗(yàn)證方法來(lái)校驗(yàn)簽名的有效性。

package com.test.aop;
import com.test.utils.Signature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 簽名攔截器
 */
@Component
@Slf4j
public class SignInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        //分配的應(yīng)用id
        String appId = request.getHeader("appId");
        //時(shí)間戳
        String timestampStr = request.getHeader("timestamp");
        //簽名
        String signature = request.getHeader("signature");
        if(StringUtils.isBlank(appId) || StringUtils.isBlank(timestampStr) || StringUtils.isBlank(signature)){
            response.setStatus(500);
            response.getWriter().println("參數(shù)錯(cuò)誤!");
            return false;
        }
        //這個(gè)密鑰實(shí)際應(yīng)該根據(jù)appId到數(shù)據(jù)庫(kù)里查出來(lái)
        String appSecret = "81343DC5-6E80-483A-A427-E3DF5FA4E5F3";
        //如果密鑰沒(méi)查到
//        if(flag){
//            response.setStatus(500);
//            response.getWriter().println("密鑰不存在!");
//        }
        //拼接數(shù)據(jù)
        String origin = appId + "\n" + appSecret + "\n" + timestampStr;
        if(!Signature.verify(appSecret, origin, signature)){
            response.setStatus(500);
            response.getWriter().println("簽名錯(cuò)誤!");
            return false;
        }
        //業(yè)務(wù)的時(shí)間戳
        long timestamp = Long.parseLong(timestampStr);
        //當(dāng)前時(shí)間戳
        long currentTimestamp = System.currentTimeMillis() / 1000;
        //10分鐘內(nèi)有效
        long timeDifference = 10 * 60;
        if(Math.abs(timestamp - currentTimestamp) > timeDifference){
            response.setStatus(500);
            response.getWriter().println("簽名過(guò)期!");
            return false;
        }
        //放行
        return true;
    }
}

配置攔截器

package com.test.config;
import com.test.aop.SignInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
 * WebMvc配置
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
	@Resource
	private SignInterceptor signInterceptor;
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		//不攔截的地址
		List<String> excludedList = new ArrayList<>();
		//swagger地址
		excludedList.add("/swagger-ui.html");
		excludedList.add("/swagger-ui.html/**");
		excludedList.add("/webjars/**");
		excludedList.add("/swagger/**");
		excludedList.add("/doc.html");
		excludedList.add("/doc.html/**");
		excludedList.add("/swagger-resources/**");
		excludedList.add("/v2/**");
		excludedList.add("/favicon.ico");
		//生成應(yīng)用id和密鑰接口不攔截
		excludedList.add("/getSecret");
		registry.addInterceptor(signInterceptor)
				.addPathPatterns("/**")//攔截所有請(qǐng)求
				.excludePathPatterns(excludedList);//排除的請(qǐng)求
		super.addInterceptors(registry);
	}
}

4.測(cè)試接口

controller定義一個(gè)測(cè)試接口

/**
 * 測(cè)試簽名
 */
@RequestMapping(value = "/sign", method = RequestMethod.GET)
public String sign() {
	return "success";
}

模擬第三方調(diào)用:

我們需要把接口請(qǐng)求頭所需參數(shù)和簽名的方法告知第三方。

接口請(qǐng)求頭參數(shù)如下:

參數(shù)名稱中文參數(shù)值
appId應(yīng)用id360aa3a3ba074da6a7bb17ae55e72d26
timestamp當(dāng)前時(shí)間戳,精確到秒

1713838208

signature簽名bjvXebFiHi2+I93BNs+8+Tl2I7k=

簽名方法:

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Signature {
    /**
     * 獲取簽名
     * @param secretKey 密鑰
     * @param data  需要簽名的數(shù)據(jù)
     * @return  簽名
     */
    public static String signWithHmacSha1(String secretKey, String data) {
        try {
            SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            return Base64.getEncoder().encodeToString(mac.doFinal(data.getBytes("UTF-8")));
        } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

生成簽名示例:

public static void main(String[] args) {
   //這里的應(yīng)用id和密鑰已實(shí)際分配的為準(zhǔn)
   String appId = "360aa3a3ba074da6a7bb17ae55e72d26";
   String appSecret = "81343DC5-6E80-483A-A427-E3DF5FA4E5F3";
   //當(dāng)前時(shí)間戳,精確到秒,示例:1713838208
   long timestamp = System.currentTimeMillis() / 1000;
   //拼接數(shù)據(jù):appId、appSecret、timestamp
   String origin = appId + "\n" + appSecret + "\n" + timestamp;
   String signature = Signature.signWithHmacSha1(appSecret, origin);
   //需要加到請(qǐng)求頭的參數(shù)
   System.out.println("appId:"+appId);
   System.out.println("timestamp:"+timestamp);
   System.out.println("signature:"+signature);
}

當(dāng)?shù)谌街澜涌谡?qǐng)求頭所需參數(shù)和簽名的方法后,就可以調(diào)用接口了

curl調(diào)用:

curl -X GET \
  http://localhost:8080/testservice/test/sign \
  -H 'appId: 360aa3a3ba074da6a7bb17ae55e72d26' \
  -H 'signature: bjvXebFiHi2+I93BNs+8+Tl2I7k=' \
  -H 'timestamp: 1713843128'

總結(jié) 這里簽名由appId + "\n" + appSecret + "\n" + timestamp,生成簽名字串時(shí)間戳用于保證簽名的有效性,即使簽名被盜用,也只能在有效時(shí)間內(nèi)使用appId、appSecret自己定義生成規(guī)則,保存到數(shù)據(jù)庫(kù)中

源碼百度網(wǎng)盤(pán)下載地址:

鏈接: https://pan.baidu.com/s/1dhtbspb3AC3M_sWBG2D-Xg?pwd=k57m

提取碼: k57m

到此這篇關(guān)于Spring Boot實(shí)現(xiàn)接口簽名驗(yàn)證的文章就介紹到這了,更多相關(guān)Spring Boot接口簽名驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 頁(yè)面設(shè)計(jì)之事件處理綜合介紹

    頁(yè)面設(shè)計(jì)之事件處理綜合介紹

    頁(yè)面設(shè)計(jì)之事件處理,當(dāng)你把界面都設(shè)計(jì)好了,總需要添加相應(yīng)的執(zhí)行動(dòng)作給組件,在有相應(yīng)的時(shí)間處理機(jī)制
    2012-12-12
  • Java JVM內(nèi)存區(qū)域詳解

    Java JVM內(nèi)存區(qū)域詳解

    下面小編就為大家?guī)?lái)一篇基于jvm java內(nèi)存區(qū)域的介紹。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-11-11
  • 詳解Spring中bean生命周期回調(diào)方法

    詳解Spring中bean生命周期回調(diào)方法

    本篇文章主要介紹了詳解Spring中bean生命周期回調(diào)方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • Java一致性Hash算法的實(shí)現(xiàn)詳解

    Java一致性Hash算法的實(shí)現(xiàn)詳解

    這篇文章主要介紹了Java一致性Hash算法的實(shí)現(xiàn)詳解,hash的意思是散列,目的將一組輸入的數(shù)據(jù)均勻的分開(kāi)、打散,往往用來(lái)配合路由算法做負(fù)載均衡,多用在分布式系統(tǒng)中,需要的朋友可以參考下
    2024-01-01
  • java serialVersionUID解決序列化類版本不一致問(wèn)題面試精講

    java serialVersionUID解決序列化類版本不一致問(wèn)題面試精講

    這篇文章主要為大家介紹了serialVersionUID解決序列化類版本不一致問(wèn)題的面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 使用jps命令查看Java進(jìn)程的詳細(xì)指南

    使用jps命令查看Java進(jìn)程的詳細(xì)指南

    jps是Java開(kāi)發(fā)者和系統(tǒng)管理員的得力助手,它簡(jiǎn)化了Java進(jìn)程監(jiān)控的過(guò)程,使得快速檢查應(yīng)用運(yùn)行狀態(tài)變得輕而易舉,在Java開(kāi)發(fā)和運(yùn)維場(chǎng)景中,jps是一個(gè)非常實(shí)用的命令行工具,本文介紹了如何有效地使用 jps命令來(lái)查看Java進(jìn)程的詳細(xì)指南,需要的朋友可以參考下
    2024-10-10
  • iReport簡(jiǎn)單使用方法圖文教程

    iReport簡(jiǎn)單使用方法圖文教程

    iReport是一個(gè)能夠創(chuàng)建復(fù)雜報(bào)表的開(kāi)源項(xiàng)目,它100%使用Java語(yǔ)言編寫(xiě),是目前全球最為流行的開(kāi)源報(bào)表設(shè)計(jì)器,由于它豐富的圖形界面,你能夠很快的創(chuàng)建出任何一種你想要的報(bào)表
    2021-10-10
  • 如何在攔截器中獲取url路徑里面@PathVariable的參數(shù)值

    如何在攔截器中獲取url路徑里面@PathVariable的參數(shù)值

    這篇文章主要介紹了如何在攔截器中獲取url路徑里面@PathVariable的參數(shù)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java中Semaphore(信號(hào)量)的使用方法

    Java中Semaphore(信號(hào)量)的使用方法

    這篇文章主要介紹了Java中Semaphore(信號(hào)量)的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • IntelliJ IDEA 最常用的配置圖文詳解

    IntelliJ IDEA 最常用的配置圖文詳解

    這篇文章給大家分享了IntelliJ IDEA 詳細(xì)圖解最常用的配置的相關(guān)知識(shí)點(diǎn)內(nèi)容,有需要的朋友們可以參考學(xué)習(xí)下。
    2018-07-07

最新評(píng)論