亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vue+Springboot實現(xiàn)接口簽名的示例代碼

 更新時間:2021年04月25日 09:30:42   作者:shadow_2155  
這篇文章主要介紹了Vue+Springboot實現(xiàn)接口簽名的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1、實現(xiàn)思路

接口簽名目的是為了,確保請求參數(shù)不會被篡改,請求的數(shù)據(jù)是否已超時,數(shù)據(jù)是否重復(fù)提交等。

接口簽名示意圖

客戶端提交請求時,將以下參數(shù)按照約定簽名方式進(jìn)行簽名,隨后將參數(shù)和簽名一同提交服務(wù)端:

1.請求頭部分(header)
appid:針對不同的調(diào)用方分配不同的appid。
noce:請求的流水號,防止重復(fù)提交。
timestamp:請求時間戳,驗證請求是否已超時失效。

2.數(shù)據(jù)部分
Path:按照path中的參數(shù)將所有key=value進(jìn)行拼接。
Query:按照所有key=value進(jìn)行拼接。
Form:按照所有key=value進(jìn)行拼接
Body:Json,按照所有key=value進(jìn)行拼接。String,整個字符串作為一個拼接。

簽名

服務(wù)端提接收交請求后,同樣通過接收的“請求頭部分”、“數(shù)據(jù)部分”的參數(shù)進(jìn)行拼接。隨后驗證客戶端提交的簽名是否正確。

2、代碼實現(xiàn)

客戶端(Vue)首先需要安裝“jsrsasign”庫,以便實現(xiàn) RSA 加密、解密、簽名、驗簽等功能。
官方地址:http://kjur.github.io/jsrsasign/
執(zhí)行以下命令:

npm install jsrsasign -save

安裝完成后,封裝sign.js

import {KJUR, KEYUTIL, hex2b64, b64tohex} from 'jsrsasign'

// 簽名算法
const ALGORITHM = 'SHA256withRSA'

// 私鑰簽名
const RSA_SIGN = (privateKey, src) => {
    const signature = new KJUR.crypto.Signature({'alg': ALGORITHM})
    // 來解析密鑰
    const priKey = KEYUTIL.getKey(privateKey) 
    signature.init(priKey)
    // 傳入待簽明文
    signature.updateString(src) 
    const a = signature.sign()
    // 轉(zhuǎn)換成base64,返回
    return hex2b64(a) 
}
// 公鑰驗簽
const RSA_VERIFY_SIGN = (publicKey, src, data) => {
    const signature = new KJUR.crypto.Signature({'alg': ALGORITHM, 'prvkeypem': publicKey})
    signature.updateString(src) 
    return signature.verify(b64tohex(data))
}

export {
    RSA_SIGN,
    RSA_VERIFY_SIGN
}

客戶端(Vue)通過sign.js進(jìn)行加簽、驗簽。

const src = '我是一段測試字符串2'

const publicKey = '-----BEGIN PUBLIC KEY-----\n' +
            'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC35wxzdTzseajkYL06hEKBCEJu\n' +
            'JQ/nySId2oTnsxbLiSTEjpAESSbML1lqkKaIwjrSFZzyLMH6DirsoEQcATqqoCDU\n' +
            '/H9QNVb5jMSAxxdQusQkTWz6k07bEuy1ppVjpGxNi8o2OGNd+lwPC/hOSDR7lpfm\n' +
            'aXLIjEwKSXzil7YAHQIDAQAB\n' +
            '-----END PUBLIC KEY-----'

const privateKey = '-----BEGIN PRIVATE KEY-----\n' +
            'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALfnDHN1POx5qORg\n' +
            'vTqEQoEIQm4lD+fJIh3ahOezFsuJJMSOkARJJswvWWqQpojCOtIVnPIswfoOKuyg\n' +
            'RBwBOqqgINT8f1A1VvmMxIDHF1C6xCRNbPqTTtsS7LWmlWOkbE2LyjY4Y136XA8L\n' +
            '+E5INHuWl+ZpcsiMTApJfOKXtgAdAgMBAAECgYB2PAcGSC7mPoW2ZvfiIlx7hurm\n' +
            '0885D1hu5yohqUOTklXgRWQUTU+zYRHU8LERJgcZQKoKDXqdIPS584Q2mRe0uZMr\n' +
            'vaiaBVEnHQreUJUQ8UN12pPUdBHDZvOk3L7/fZHk6A8uy5e09p2rsn+Vfki3zijp\n' +
            '7Pd758HMtjuiHBb2QQJBAOuN6jdWBr/zb7KwM9N/cD1jJd6snOTNsLazH/Z3Yt0T\n' +
            'jlsFmRJ6rIt/+jaLKG6YTR8SFyW5LIQTbreeQHPw4FECQQDH3Wpd/mBMMcgpxLZ0\n' +
            'F5p1ieza+VA5fbxkQ0hdubEP26B6YwhkTB/xMSOwEjmUI57kfgOTvub36/peb8rI\n' +
            'JdwNAkB3fzwlrGeqMzYkIU15avomuki46TqCvHJ8jOyXHUOzQbuDI5jfDgrAjkEC\n' +
            'MKBnUq41J/lEMueJbU5KqmaqKrWxAkAyexlHnl1iQVymOBpBXkjUET8y26/IpZp0\n' +
            '1I2tpp4zPCzfXK4c7yFOQTQbX68NXKXgXne21Ivv6Ll3KtNUFEPtAkBcx5iWU430\n' +
            '0/s6218/enaa8jgdqw8Iyirnt07uKabQXqNnvbPYCgpeswEcSvQqMVZVKOaMrjKO\n' +
            'G319Es83iq/m\n' +
            '-----END PRIVATE KEY-----\n'


console.log('明文:', src)
const data = RSA_SIGN(privateKey, src)
console.log('簽名后的結(jié)果:', data)

const res = RSA_VERIFY_SIGN(publicKey, src, data)
console.log('驗簽結(jié)果:', res)

服務(wù)端(Spring boot)接收請求后,需要對數(shù)據(jù)和簽名,進(jìn)行驗證。

首先引入依賴——hutool工具包,Hutool是一個Java工具包,也只是一個工具包,它幫助我們簡化每一行代碼,減少每一個方法,讓Java語言也可以“甜甜的”。

官網(wǎng)地址:https://www.hutool.cn/

在pom.xml下增加如下配置:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.3.5</version>
</dependency>

服務(wù)端(Spring boot)首先要獲取客戶端(Vue)請求的數(shù)據(jù),上文已經(jīng)描述了請求的數(shù)據(jù)有兩部分,分別是“請求頭部分”、“數(shù)據(jù)部分”。所以需要配置攔截器,對以上兩部分進(jìn)行獲取。

配置攔截器(MyInterceptor.java),代碼如下:

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //獲取請求參數(shù)
        String queryString = request.getQueryString();
        log.info("請求參數(shù):{}", queryString);

        // 獲取header
        log.info("key:{}",request.getHeader("timestamp"));

        MyHttpServletRequestWrapper myRequestWrapper = new MyHttpServletRequestWrapper(request);
        //獲取請求body
        byte[] bodyBytes = StreamUtils.copyToByteArray(myRequestWrapper.getInputStream());
        String body = new String(bodyBytes, request.getCharacterEncoding());

        log.info("請求體:{}", body);

        return true;
    }
}

在獲取“請求體body”時,由于“HttpServletRequest”只能讀取一次,攔截器讀取后,后續(xù)Controller在讀取時為空,所以需要重寫HttpServletRequestWrapper:

import org.springframework.util.StreamUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;


public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {

    /**
     * 緩存下來的HTTP body
     */
    private byte[] body;

    public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = StreamUtils.copyToByteArray(request.getInputStream());
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        InputStream bodyStream = new ByteArrayInputStream(body);
        return new ServletInputStream(){

            @Override
            public int read() throws IOException {
                return bodyStream.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}

之后,需要創(chuàng)建過濾器,將“MyHttpServletRequestWrapper” 替換“ServletRequest”,代碼如下:

import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Slf4j
public class RepeatedlyReadFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
        if(servletRequest instanceof HttpServletRequest) {
            requestWrapper = new MyHttpServletRequestWrapper((HttpServletRequest) servletRequest);
        }
        if(requestWrapper == null) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            filterChain.doFilter(requestWrapper, servletResponse);
        }

    }

    @Override
    public void destroy() {

    }
}

之后創(chuàng)建自定義配置,CorsConfig.java,將過濾器、攔截器加入配置:

import com.xyf.interceptor.MyInterceptor;
import com.xyf.interceptor.RepeatedlyReadFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Configuration
public class CorsConfig extends WebMvcConfigurationSupport {

    private MyInterceptor myInterceptor;

    @Autowired
    public CorsConfig (MyInterceptor myInterceptor){
        this.myInterceptor = myInterceptor;
    }

    // 注冊過濾器
    @Bean
    public FilterRegistrationBean<RepeatedlyReadFilter> repeatedlyReadFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        RepeatedlyReadFilter repeatedlyReadFilter = new RepeatedlyReadFilter();
        registration.setFilter(repeatedlyReadFilter);
        registration.addUrlPatterns("/*");
        return registration;
    }


    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        // addPathPatterns添加需要攔截的命名空間;
        // excludePathPatterns添加排除攔截命名空間

        registry.addInterceptor(myInterceptor).addPathPatterns("/**");
        //.excludePathPatterns("/api/sys/login")
    }

}

最后,完成驗簽,代碼如下:

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;


byte[] data = "我是一段測試字符串2".getBytes();
        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC35wxzdTzseajkYL06hEKBCEJu\n" +
                "JQ/nySId2oTnsxbLiSTEjpAESSbML1lqkKaIwjrSFZzyLMH6DirsoEQcATqqoCDU\n" +
                "/H9QNVb5jMSAxxdQusQkTWz6k07bEuy1ppVjpGxNi8o2OGNd+lwPC/hOSDR7lpfm\n" +
                "aXLIjEwKSXzil7YAHQIDAQAB";

Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA,null,publicKey);

//客戶端傳來的簽名
String qm = "IhY3LNuFn0isud1Pk6BL2eJV3Jl/UzDCYsdG9CYyJwOGqwnzStsv/RiYLnVP4bnQh1NRPMazY6ux/5Zz5Ypcx6RI5W1p5BDbO2afuIZX7x/eIu5utwsanhbxEfvm3XOsyuTbnMDh6BQUrXb4gUz9qgt9IXWjQdqnQRRv3ywzWcA=";
byte[] signed = Base64.decode(qm);

//驗證簽名
boolean verify = sign.verify(data, signed);

3、公鑰、私鑰生成

可通過一些網(wǎng)站在線生成公鑰、私鑰
網(wǎng)址:https://www.bejson.com/enc/rsa/

bejson在線生成公鑰、私鑰

4、其他問題

由于客戶端加簽、服務(wù)端驗簽。所以加簽、驗簽的方式務(wù)必一致,否則將無法驗證簽名。Vue、Java有不同的簽名工具庫,使用前要做好測試。

到此這篇關(guān)于Vue+Springboot實現(xiàn)接口簽名的示例代碼的文章就介紹到這了,更多相關(guān)Springboot 接口簽名內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • 基于Vue3+Element Plus 實現(xiàn)多表單校驗demo

    基于Vue3+Element Plus 實現(xiàn)多表單校驗demo

    表單校驗在日常的開發(fā)需求中是一種很常見的需求,通常在提交表單發(fā)起請求前校驗用戶輸入是否符合規(guī)則,通常只需formRef.value.validate()即可校驗,本文給大家介紹基于Vue3+Element Plus 實現(xiàn)多表單校驗demo,感興趣的朋友一起看看吧
    2024-06-06
  • 一文詳解vue-router中的導(dǎo)航守衛(wèi)

    一文詳解vue-router中的導(dǎo)航守衛(wèi)

    vue-router提供的導(dǎo)航守衛(wèi)主要用來通過跳轉(zhuǎn)或取消的方式守衛(wèi)導(dǎo)航,在 vue-router 中,導(dǎo)航守衛(wèi)是一種非常重要的功能,所以本文將詳細(xì)講解一下vue-router中的導(dǎo)航守衛(wèi),感興趣的同學(xué)跟著小編一起來看看吧
    2023-07-07
  • vue 動態(tài)生成拓?fù)鋱D的示例

    vue 動態(tài)生成拓?fù)鋱D的示例

    這篇文章主要介紹了vue 動態(tài)生成拓?fù)鋱D的示例,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下
    2021-01-01
  • 淺談vue的iview列表table render函數(shù)設(shè)置DOM屬性值的方法

    淺談vue的iview列表table render函數(shù)設(shè)置DOM屬性值的方法

    下面小編就為大家?guī)硪黄獪\談vue的iview列表table render函數(shù)設(shè)置DOM屬性值的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 關(guān)于vue 結(jié)合原生js 解決echarts resize問題

    關(guān)于vue 結(jié)合原生js 解決echarts resize問題

    這篇文章主要介紹了關(guān)于vue 結(jié)合原生js 解決echarts resize問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • vue-vuex中使用commit提交mutation來修改state的方法詳解

    vue-vuex中使用commit提交mutation來修改state的方法詳解

    今天小編就為大家分享一篇vue-vuex中使用commit提交mutation來修改state的方法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • vue源碼之首次渲染過程詳解

    vue源碼之首次渲染過程詳解

    這篇文章主要為大家詳細(xì)介紹了vue源碼之首次渲染過程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • vue中的非父子間的通訊問題簡單的實例代碼

    vue中的非父子間的通訊問題簡單的實例代碼

    這篇文章主要介紹了vue中的非父子間的通訊問題簡單的實例代碼,需要的朋友可以參考下
    2017-07-07
  • element-ui 彈窗組件封裝的步驟

    element-ui 彈窗組件封裝的步驟

    這篇文章主要介紹了element-ui 彈窗組件封裝的步驟,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下
    2021-01-01
  • vue登錄路由驗證的實現(xiàn)

    vue登錄路由驗證的實現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了vue登錄路由驗證的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12

最新評論