当前位置:首页 > 通信资讯 > 正文

使用webassembly对前端api请求进行签名(使用webassembly对前端api请求进行签名)

背景

server端处理WebAPI请求的安全问题:

  1. 请求重放 (eg. 月饼抢购场景中,程序员通过脚本直接访问接口)
  2. 参数篡改 (eg. 会话劫持场景中,将应该抢购到的月饼归属人改为自己)
  3. 脚本攻击 (eg. 综合前两种场景,使用技术手段构建的请求进行攻击,如信息窃取,漏洞攻击)
  4. 可信客户端请求 (eg. 以上所有场景根因均为访问客户端不可信并不可证伪)

解决方案

  1. 对请求参数+cnonce (客户端生成的一次性随机字符串) 进行hash签名
  2. 以secret作为盐值
  3. 将签名作为header值传递给server端
  4. server端在redis中查验是否已有重复签名,如有重复直接拒绝请求(防止请求重放)
  5. server端对签名值进行校验
  6. 校验通过之后将该签名值作为key值,存入redis

总体流程如下图所示:

使用webassembly对前端api请求进行签名(使用webassembly对前端api请求进行签名)

代码示例

前端使用示例(TypeScript Vue3 版本):

  1. <scriptsetup>
  2. import{onMounted}from"vue";
  3. importinitWasm,{sign}from"./pkg/sign.js";//通过wasm-pack打包生成的二进制包的入口文件
  4. import{v4asuuidv4}from'uuid';//此示例以生成的UUID作为cnonce随机字符串
  5. onMounted(async()=>{
  6. awaitinitWasm()
  7. })
  8. constsendRequest=()=>{
  9. constcnonce=uuidv4()
  10. constparams:EncryptedParams={
  11. name:'John',
  12. age:23,
  13. breed:'dog',
  14. ts:Date.now()
  15. }
  16. constwasmSignature=sign(JSON.stringify(params),cnonce);
  17. ...
  18. axios.post(something);
  19. }
  20. </script>

签名机制示例,server端接受到请求时,应该同时获得签名值以及cnonce一次性字符串,按照下面同样的签名顺序进行签名,比对前端传入的签名以及server端生成的签名进行校验:

  1. constencryptedSign=(message:string,cnonce:string):string=>{
  2. constsecret='XXXXXXX'//该签名盐值可以自行生成,生成之后需要重新编译rust应用,生成新的wasm包
  3. consthashDigest=sha256(`${cnonce}|${message}`)
  4. consthmacDigest=Base64.stringify(hmacSHA512(hashDigest.toString().toUpperCase(),secret))
  5. returnhmacDigest.toString().toUpperCase()
  6. }

签名机制示例 (rust 版本):

  1. externcratewasm_bindgen;
  2. usering::hmac;
  3. usering::digest::{Context,SHA256};
  4. usedata_encoding::BASE64;
  5. usedata_encoding::HEXUPPER;
  6. usewasm_bindgen::prelude::*;
  7. #[wasm_bindgen]
  8. pubfnron_weasley_sign(message:&str,cnonce:&str)->String{
  9. constSECRET:&str=std::env!("SECRET");
  10. letmutcontext=Context::new(&SHA256);
  11. context.update(format!("{}|{}",cnonce,message).as_bytes());
  12. letsha256_result=context.finish();
  13. letsha256_result_str=format!("{}",HEXUPPER.encode(sha256_result.as_ref()));
  14. letkey=hmac::Key::new(hmac::HMAC_SHA512,SECRET.as_bytes());
  15. letmac=hmac::sign(&key,sha256_result_str.as_bytes());
  16. letb64_encoded_sig=BASE64.encode(mac.as_ref());
  17. returnb64_encoded_sig.to_uppercase();
  18. }

构建rust源代码,并生成对应的二进制包

首先在项目的github地址

https://github.com/swearer23/ron-weasley 下载源代码

之后按照README文件的步骤安装编译环境(以*nix环境为例)

安装cargo

由于我们使用cargo作为rust环境的管理器,所以第一步安装cargo

安装完成后在命令行输入cargo -v 查看是否安装成功

  1. cargo-v#可能需要重新启动终端
  2. Rust'spackagemanager
  3. USAGE:
  4. cargo[+toolchain][OPTIONS][SUBCOMMAND]
  5. OPTIONS:
  6. -V,--versionPrintversioninfoandexit
  7. --listListinstalledcommands
  8. --explain<CODE>Run`rustc--explainCODE`
  9. -v,--verboseUseverboseoutput(-vvveryverbose/build.rsoutput)
  10. -q,--quietNooutputprintedtostdout
  11. --color<WHEN>Coloring:auto,always,never
  12. --frozenRequireCargo.lockandcacheareuptodate
  13. --lockedRequireCargo.lockisuptodate
  14. --offlineRunwithoutaccessingthenetwork
  15. --config<KEY=VALUE>...Overrideaconfigurationvalue(unstable)
  16. -Z<FLAG>...Unstable(nightly-only)flagstoCargo,see'cargo-Zhelp'fordetails
  17. -h,--helpPrintshelpinformation
  18. Somecommoncargocommandsare(seeallcommandswith--list):
  19. build,bCompilethecurrentpackage
  20. check,cAnalyzethecurrentpackageandreporterrors,butdon'tbuildobjectfiles
  21. cleanRemovethetargetdirectory
  22. doc,dBuildthispackage'sanditsdependencies'documentation
  23. newCreateanewcargopackage
  24. initCreateanewcargopackageinanexistingdirectory
  25. run,rRunabinaryorexampleofthelocalpackage
  26. test,tRunthetests
  27. benchRunthebenchmarks
  28. updateUpdatedependencieslistedinCargo.lock
  29. searchSearchregistryforcrates
  30. publishPackageanduploadthispackagetotheregistry
  31. installInstallaRustbinary.Defaultlocationis$HOME/.cargo/bin
  32. uninstallUninstallaRustbinary
  33. See'cargohelp<command>'formoreinformationonaspecificcommand.

安装wasm-pack

要构建二进制包,需要一个额外工具 wasm-pack。它会帮助我们把代码编译成 WebAssembly 并构建出适用于web环境的wasm包。使用下面的命令可以下载并安装:

  1. cargoinstallwasm-pack

编译wasm

wasm-pack安装成功后,执行下面的命令以编译wasm包

  1. SECRET=wasm-packbuild--target=web--release

<your-secret>替换为你的签名盐值

第一次构建和编译时间会比较长,需要下载依赖的rust库并编译,请耐心等待

如果速度仍然很慢,建议更换cargo国内源

更换 cargo 源

在你的cargo文件夹下新建 config 文件

macos中,文件夹地址在 ~/.cargo

  1. cd~/.cargo
  2. touchconfig

然后编辑config文件,添加如下内容:

  1. [source.crates-io]
  2. registry="https://github.com/rust-lang/crates.io-index"
  3. replace-with='ustc'
  4. [source.ustc]
  5. registry="git://mirrors.ustc.edu.cn/crates.io-index"

即可更换为ustc的源

集成

执行wasm-pack命令打包会得到一个名为pkg的文件夹,位于项目的根目录下

将其放入要使用的前端项目中,即可以像上面代码示例章节所描述的方式进行集成和调用

附录

  • rust 项目地址:https://github.com/swearer23/ron-weasley
  • vue3 调用方式示例项目地址:https://github.com/swearer23/harry-porter (内含有secret=123456的wasm包,可以用于示例)

原文地址:https://www.toutiao.com/a7045923113728573982/

如果您对该产品感兴趣,请填写办理(客服微信:xiaoxiongyidong)

为您推荐:

发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。