Vue框架怎样实现接口签名,要点有哪些

Admin 2022-10-20 群英技术资讯 349 次浏览

这篇文章主要讲解了“Vue框架怎样实现接口签名,要点有哪些”,文中的讲解内容简单、清晰、详细,对大家学习或是工作可能会有一定的帮助,希望大家阅读完这篇文章能有所收获。下面就请大家跟着小编的思路一起来学习一下吧。

1、实现思路

接口签名目的是为了,确保请求参数不会被篡改,请求的数据是否已超时,数据是否重复提交等。

接口签名示意图

客户端提交请求时,将以下参数按照约定签名方式进行签名,随后将参数和签名一同提交服务端:

1.请求头部分(header)
appid:针对不同的调用方分配不同的appid。
noce:请求的流水号,防止重复提交。
timestamp:请求时间戳,验证请求是否已超时失效。

2.数据部分
Path:按照path中的参数将所有key=value进行拼接。
Query:按照所有key=value进行拼接。
Form:按照所有key=value进行拼接
Body:Json,按照所有key=value进行拼接。String,整个字符串作为一个拼接。

签名

服务端提接收交请求后,同样通过接收的“请求头部分”、“数据部分”的参数进行拼接。随后验证客户端提交的签名是否正确。

2、代码实现

客户端(Vue)首先需要安装“jsrsasign”库,以便实现 RSA 加密、解密、签名、验签等功能。
官方地址:http://kjur.github.io/jsrsasign/
执行以下命令:

?
1 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()      // 转换成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进行加签、验签。

?
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( '签名后的结果:' , data)   const res = RSA_VERIFY_SIGN(publicKey, src, data) console.log( '验签结果:' , res)

服务端(Spring boot)接收请求后,需要对数据和签名,进行验证。

首先引入依赖——hutool工具包,Hutool是一个Java工具包,也只是一个工具包,它帮助我们简化每一行代码,减少每一个方法,让Java语言也可以“甜甜的”。

官网地址:https://www.hutool.cn/

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

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

服务端(Spring boot)首先要获取客户端(Vue)请求的数据,上文已经描述了请求的数据有两部分,分别是“请求头部分”、“数据部分”。所以需要配置拦截器,对以上两部分进行获取。

配置拦截器(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 {          //获取请求参数          String queryString = request.getQueryString();          log.info( "请求参数:{}" , 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”只能读取一次,拦截器读取后,后续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()));      } }

之后,需要创建过滤器,将“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() {        } }

之后创建自定义配置,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、公钥、私钥生成

可通过一些网站在线生成公钥、私钥
网址:https://www.bejson.com/enc/rsa/

bejson在线生成公钥、私钥

4、其他问题

由于客户端加签、服务端验签。所以加签、验签的方式务必一致,否则将无法验证签名。Vue、Java有不同的签名工具库,使用前要做好测试。


感谢各位的阅读,以上就是“Vue框架怎样实现接口签名,要点有哪些”的内容了,经过本文的学习后,相信大家对Vue框架怎样实现接口签名,要点有哪些都有更深刻的体会了吧。这里是群英网络,小编将为大家推送更多相关知识点的文章,欢迎关注! 群英智防CDN,智能加速解决方案
标签: Vue接口签名

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

猜你喜欢

成为群英会员,开启智能安全云计算之旅

立即注册
专业资深工程师驻守
7X24小时快速响应
一站式无忧技术支持
免费备案服务
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
在线客服
微信公众号
返回顶部
返回顶部 返回顶部
在线客服
在线客服