Expires=1730198146&OSSAccessKeyId=LTAI4FwmPQBRwQf7fJpXXJEo&Signature=REz3gWtn8e4K1bDnho9%2FP5JxnVc%3


问题出现的背景:前端要调用后端的一个方法https://api.crossbiog.com/brand/admin/detail/?id=78获取introduceAttachmentList数组中的url,但是获取到这个"url": “56/brand/旭包鲜轮播图1750375_696868.jpg”,后,拼接基础https://www.crossbiog.com/的地址得到一个完整的地址https://www.crossbiog.com/56/brand/%E6%97%AD%E5%8C%85%E9%B2%9C%E8%BD%AE%E6%92%AD%E5%9B%BE1750375_696868.jpg
但是发现这个地址被服务器拒接访问,因为需要签名认证参数(Expires、OSSAccessKeyId、Signature)阿里云服务器oss才可以访问图片,这个时候就得生成签名认证,最后通过寻找后端代码找了好久才找到这个方法,可以返回签名认证。

{
    "code": 0,
    "msg": "成功",
    "data": {
        "id": 78,
        "region": 3,
        "code": "B240910204913-5257",
        "logo": "brand-logo/旭包鲜LOGO_803497.jpg",
        "name": "旭包鲜",
        "englishName": "AsahiKASEI",
        "location": "日本",
        "introduce": "旭包鲜®是具有代表性的日本综合化学品生产企业—旭化成集团旗下的旭化成家庭用品株式会社所持有的厨房用品品牌。它所生产的保鲜膜日语名称为「サランラップ®」在日本已经畅销超过60年以上。 PVDC材质的保鲜膜以其优良的密封性、可微波炉加热、结实易撕等高性能品质,在日本是享有盛誉的长期畅销产品。2001年开始正式进入中国市场。现在,在中国的各大实体超市以及网购平台均有销售。",
        "ranks": 0,
        "nameList": [

        ],
        "logoAttachmentList": [

        ],
        "introduceAttachmentList": [
            {
                "name": "旭包鲜轮播图1750375_696868.jpg",
                "url": "56/brand/旭包鲜轮播图1750375_696868.jpg",
                "size": 225136,
                "sizeStr": "219.86K",
                "thumbnail": "56/brand/旭包鲜轮播图1750375_696868-thumbnail.jpg",
                "width": null,
                "height": null
            },
            {
                "name": "旭包鲜轮播图2750375_435717.jpg",
                "url": "56/brand/旭包鲜轮播图2750375_435717.jpg",
                "size": 225136,
                "sizeStr": "219.86K",
                "thumbnail": "56/brand/旭包鲜轮播图2750375_435717-thumbnail.jpg",
                "width": null,
                "height": null
            },
            {
                "name": "旭包鲜轮播图3750375_922227.jpg",
                "url": "56/brand/旭包鲜轮播图3750375_922227.jpg",
                "size": 225136,
                "sizeStr": "219.86K",
                "thumbnail": "56/brand/旭包鲜轮播图3750375_922227-thumbnail.jpg",
                "width": null,
                "height": null
            },
            {
                "name": "旭包鲜轮播图4750375_218746.jpg",
                "url": "56/brand/旭包鲜轮播图4750375_218746.jpg",
                "size": 225136,
                "sizeStr": "219.86K",
                "thumbnail": "56/brand/旭包鲜轮播图4750375_218746-thumbnail.jpg",
                "width": null,
                "height": null
            },
            {
                "name": "旭包鲜轮播图5750375_774655.jpg",
                "url": "56/brand/旭包鲜轮播图5750375_774655.jpg",
                "size": 225136,
                "sizeStr": "219.86K",
                "thumbnail": "56/brand/旭包鲜轮播图5750375_774655-thumbnail.jpg",
                "width": null,
                "height": null
            }
        ],
        "editAuth": 1
    }
}
https://www.crossbiog.com/56/brand/%E6%97%AD%E5%8C%85%E9%B2%9C%E8%BD%AE%E6%92%AD%E5%9B%BE1750375_696868.jpg
这个地址不可以访问阿里云oss,这个地址从后端获取的其中一部分56/brand/旭包鲜轮播图1750375_696868.jpg然后拼接而成的。

在这里插入图片描述

https://www.crossbiog.com//56/brand/%E6%97%AD%E5%8C%85%E9%B2%9C%E8%BD%AE%E6%92%AD%E5%9B%BE1750375_696868.jpg?
Expires=1730198146&OSSAccessKeyId=LTAI4FwmPQBRwQf7fJpXXJEo&Signature=REz3gWtn8e4K1bDnho9%2FP5JxnVc%3D
这个地址就可以访问阿里云oss

两个链接的主要区别在于第二个链接中包含了一些查询参数(ExpiresOSSAccessKeyIdSignature),这些参数通常是用于访问云存储服务(如阿里云OSS)时的签名认证信息,用于验证请求的有效性和安全性。

为什么第一个链接无法访问,而第二个可以:

  1. 签名认证

    • 第二个链接包含了签名认证参数(ExpiresOSSAccessKeyIdSignature),这些参数使得链接能够通过服务器的认证,因此可以访问。
    • 第一个链接没有包含这些认证参数,因此无法通过认证,导致无法访问。
  2. 权限问题

    • 没有签名的链接可能没有权限访问资源,特别是当资源存储在需要权限验证的云存储服务上时。
  3. 链接格式

    • 第二个链接中的额外斜杠(//)可能是一个错误,但这并不影响链接的功能,因为URL解析器会自动处理多余的斜杠。

解决方法:

  • 检查链接

    • 确保链接的格式正确,特别是签名参数是否完整且有效。
  • 获取有效的签名

    • 如果你是资源的拥有者或有权访问资源,确保生成有效的签名参数,并将其添加到链接中。
  • 联系资源提供者

    • 如果你无法生成签名,可能需要联系资源的提供者获取正确的链接。
  • 检查网络连接

    • 确保网络连接正常,有时网络问题也可能导致链接无法访问。
  • 重试链接

    • 有时服务器可能暂时不可用,稍后重试可能会解决问题。
const { imageBaseUrl } = require('../../config/config');
const config = require('../../config/config');

Page({
  data: {
    swiperImages:[
    ],// 初始化轮播图数据
    brand: {},
    showBottomImage: true
  },
  

  // 获取 token
  getToken: function() {
    return new Promise((resolve,reject)=>{
      // 模拟登录获取 token
      // wx.request({
      //   url: config.baseUrl + config.signInUrl, // 使用配置文件中的URL
      //   method: 'POST',
      //   data: {
      //     username: '18661977581', // 替换为您的用户名
      //     password: 'XXXXX'  // 替换为您的密码
      //   },
      //   header: {
      //     'content-type': 'application/x-www-form-urlencoded' // 设置请求头为表单格式
      //   },
      //   success: (res) => {
      //     console.log("res="+res)
      //     console.log("res.statusCode="+res.statusCode)
      //     console.log("res.data = " + res.data);
      //     console.log("res.data = " + JSON.stringify(res.data));
      //     // 检查返回的数据结构
      //     if (res.statusCode === 200 && res.data && res.data.data && res.data.data.token) {
      //       let token = res.data.data.token; 
      //       console.log("后端获取到的token="+token)
      //       wx.setStorageSync('token', token);
      //       resolve(token)
      //     } else {
      //       reject(new Error('获取token失败,响应数据不符合预期'));
      //     }
      //   },
      //   fail: (err) => {
      //     reject(new Error('请求失败'));
      //   }
      // });
      const token = wx.getStorageSync('token')
      resolve(token)
    });
  },

    // 发送请求获取品牌数据
    fetchBrandData: function() {
      this.getToken().then((token) => {
        console.log("获取品牌数据前需要携带token=" + token);
        if (!token) {
          wx.showToast({
            title: '获取 token 失败,请重试',
            icon: 'none'
          });
          return;
        }

        function requestGeneral(url,method,data={},header={}){
          return new Promise((resolve,reject)=>{
            wx.request({
              url: config.baseUrl + url,
              method:method,
              data:data,
              header:{
                ...header,
                'content-type':'application/x-www-form-urlencoded',
              },
              success:(res)=>{
                if(res.statusCode === 200){
                  resolve(res.data);
                }else{
                  reject(new Error('请求失败'));
                }
              },
              fail:(err)=>{
                reject(new Error('请求失败'));
              }
            })
          })
        }
        requestGeneral(config.getBrandDetailUrl,'GET', {page:0,size:10}, { 'token': token })
          .then((res) => {
            console.log("then(res):",res)
            if (res.code === 0) {
              console.log("res.code=",res.code)
              const data = res.data || {};
              console.log("res.data=",data)
              const content = res.data.content;
              console.log("content="+content)
              const brand = content[0];

              this.setData({
                brand: brand,
              });
            } else {
              wx.showToast({
                title: '数据加载失败',
                icon: 'none'
              });
            }
          })
          .catch((err) => {
            wx.showToast({
              title: '请求失败',
              icon: 'none'
            });
        });
        
      })
      .catch((err) => {
        wx.showToast({
          title: err.message,
          icon: 'none'
        });
      });
    },
    
    // 构建查询参数字符串
    buildQueryParams: function(params) {
      return Object.keys(params).map(key => `${key}=${encodeURIComponent(params[key])}`).join('&');
    },
    // 发送请求获取轮播图数据
    fetchSwiperImages: function() {
      this.getToken().then((token) => {
      function requestGeneral(url,method,data={},header={}){
        return new Promise((resolve,reject)=>{
          wx.request({
            url: config.baseUrl + url,
            method:method,
            data:data,
            header:{
              ...header,
              'content-type':'application/x-www-form-urlencoded',
            },
            success:(res)=>{
              if(res.statusCode === 200){
                resolve(res.data);
              }else{
                reject(new Error('请求失败'));
              }
            },
            fail:(err)=>{
              reject(new Error('请求失败'));
            }
          })
        })
      }
      const url = config.getSwiperImagesUrl; // 不再替换路径参数
      const id = { id: 78 }; // 使用查询参数
      // console.log("请求轮播图数据的URL:", config.baseUrl + url + '?' + this.buildQueryParams(id));
      requestGeneral(url, 'GET', id, { 'token': token })
        .then((res) => {
          console.log("fetchSwiperImages then(res):", res);
          if (res.code === 0) {
            const data = res.data || {};
            const swiperImages = data.introduceAttachmentList ? data.introduceAttachmentList.map(item =>imageBaseUrl+ item.url) : []; 
            console.log("这个图片地址没有加密,不能访问"+swiperImages)
            const introduceAttachmentListUrl = data.introduceAttachmentList ? data.introduceAttachmentList.map(item => item.url) : []; 
            console.log("introduceAttachmentListUrl"+introduceAttachmentListUrl)

            
            // 请求后端生成签名 URL
            const fetchSignedUrls = (urls) => {
              console.log("urls:"+urls)
              return Promise.all(urls.map(url => {
                  console.log("请求签名 URL 的资源:", url); // 输出当前请求的 URL 
                  return new Promise((resolve, reject) => {
                      wx.request({
                          // url: 'http://localhost:8087/oss/download/',
                          url:  config.baseUrl +'/oss/download/',
                          method: 'GET',
                          data: {  url: url },
                          header: {
                              'token':token,
                              'Content-Type': 'application/json'
                          },
                          success: (res) => {
                            console.log("res.data:"+res.data)
                              if (res.statusCode === 200 ) {
                                  resolve(res.data.data);
                                  console.log("res.data.data:"+res.data.data)
                              } else {
                                  reject(new Error('签名 URL 响应数据不符合预期,响应数据:' + JSON.stringify(res.data)));
                              }
                          },
                          fail: (err) => {
                              reject(new Error('请求失败', err));
                          }
                      });
                  });
              }));
            };
            // fetchSignedUrls(introduceAttachmentListUrl)
            //   .then((signedUrls) => {
            //     this.setData({
            //       swiperImages: config.imageBaseUrl + signedUrls
            //     });
            //   })
            //   .catch((err) => {
            //     console.error("获取签名 URL 失败:", err);
            //     wx.showToast({
            //       title: '轮播图数据加载失败',
            //       icon: 'none'
            //     });
            //   });

            fetchSignedUrls(introduceAttachmentListUrl)
            .then((signedUrls) => {
              // 将签名 URL 与 base URL 拼接
              const completeUrls = signedUrls.map(signedUrl => config.imageBaseUrl + signedUrl);
              this.setData({
                swiperImages: completeUrls
              });
            })
            .catch((err) => {
              console.error("获取签名 URL 失败:", err);
              wx.showToast({
                title: '轮播图数据加载失败',
                icon: 'none'
              });
            });
          } else {
            wx.showToast({
              title: '轮播图数据加载失败',
              icon: 'none'
            });
          }
        })
        .catch((err) => {
          wx.showToast({
            title: '请求失败',
            icon: 'none'
          });
        });
      })
    },

  // 页面加载时调用
  onLoad: function() {
    console.log("页面加载"); // 添加日志输出
    this.fetchBrandData(); // 加载品牌数据
    this.fetchSwiperImages();
  }
});

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值