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

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

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

1、實(shí)現(xiàn)思路

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

接口簽名示意圖

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

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

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)行拼接。隨后驗(yàn)證客戶端提交的簽名是否正確。

2、代碼實(shí)現(xiàn)

客戶端(Vue)首先需要安裝“jsrsasign”庫,以便實(shí)現(xiàn) RSA 加密、解密、簽名、驗(yàn)簽等功能。
官方地址: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) 
}
// 公鑰驗(yàn)簽
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)行加簽、驗(yà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('驗(yàn)簽結(jié)果:', res)

服務(wù)端(Spring boot)接收請求后,需要對數(shù)據(jù)和簽名,進(jìn)行驗(yà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")
    }

}

最后,完成驗(yàn)簽,代碼如下:

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);

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

3、公鑰、私鑰生成

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

bejson在線生成公鑰、私鑰

4、其他問題

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

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

相關(guān)文章

最新評論

晋中市| 万宁市| 本溪| 镶黄旗| 乐清市| 内丘县| 广安市| 岗巴县| 河源市| 永定县| 屏东县| 油尖旺区| 安化县| 赤峰市| 庆云县| 烟台市| 宿州市| 商城县| 南部县| 焉耆| 宣化县| 开鲁县| 若尔盖县| 裕民县| 四平市| 武川县| 鹤庆县| 安塞县| 九台市| 麦盖提县| 莱西市| 介休市| 通化县| 关岭| 七台河市| 宣恩县| 伽师县| 荔波县| 仁怀市| 蓬安县| 昌江|