verify-request-sign.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. const crypto = require('crypto')
  2. const createConfig = require('uni-config-center')
  3. const { verifyHttpInfo } = require('uni-cloud-s2s')
  4. const { ERROR } = require('../common/error')
  5. const s2sConfig = createConfig({
  6. pluginId: 'uni-cloud-s2s'
  7. })
  8. const needSignFunctions = new Set([
  9. 'externalRegister',
  10. 'externalLogin',
  11. 'updateUserInfoByExternal'
  12. ])
  13. module.exports = function () {
  14. const methodName = this.getMethodName()
  15. const { source } = this.getUniversalClientInfo()
  16. // 指定接口需要鉴权
  17. if (!needSignFunctions.has(methodName)) return
  18. // 非 HTTP 方式请求拒绝访问
  19. if (source !== 'http') {
  20. throw {
  21. errCode: ERROR.ILLEGAL_REQUEST
  22. }
  23. }
  24. // 支持 uni-cloud-s2s 验证请求
  25. if (s2sConfig.hasFile('config.json')) {
  26. try {
  27. if (!verifyHttpInfo(this.getHttpInfo())) {
  28. throw {
  29. errCode: ERROR.ILLEGAL_REQUEST
  30. }
  31. }
  32. } catch (e) {
  33. if (e.errSubject === 'uni-cloud-s2s') {
  34. throw {
  35. errCode: ERROR.ILLEGAL_REQUEST,
  36. errMsg: e.errMsg
  37. }
  38. }
  39. throw e
  40. }
  41. return
  42. }
  43. if (!this.config.requestAuthSecret || typeof this.config.requestAuthSecret !== 'string') {
  44. throw {
  45. errCode: ERROR.CONFIG_FIELD_REQUIRED,
  46. errMsgValue: {
  47. field: 'requestAuthSecret'
  48. }
  49. }
  50. }
  51. const timeout = 20 * 1000 // 请求超过20秒不能再请求,防止重放攻击
  52. const { headers, body: _body } = this.getHttpInfo()
  53. const { 'uni-id-nonce': nonce, 'uni-id-timestamp': timestamp, 'uni-id-signature': signature } = headers
  54. const body = JSON.parse(_body).params || {}
  55. const bodyStr = Object.keys(body)
  56. .sort()
  57. .filter(item => typeof body[item] !== 'object')
  58. .map(item => `${item}=${body[item]}`)
  59. .join('&')
  60. if (isNaN(Number(timestamp)) || (Number(timestamp) + timeout) < Date.now()) {
  61. throw {
  62. errCode: ERROR.ILLEGAL_REQUEST
  63. }
  64. }
  65. const reSignature = crypto.createHmac('sha256', `${this.config.requestAuthSecret + nonce}`).update(`${timestamp}${bodyStr}`).digest('hex')
  66. if (signature !== reSignature.toUpperCase()) {
  67. throw {
  68. errCode: ERROR.ILLEGAL_REQUEST
  69. }
  70. }
  71. }