微信小程序 - 05_网络数据请求(wx.request、get/post、跳过request合法域名校验、案例练习)


欢迎访问笔者个人技术博客: http://rukihuang.xyz/

01 请求限制

  • 处于安全性的考虑,小程序官方对数据接口的请求做出了两个限制:
    • 只能请求HTTPS类型的接口
    • 必须将接口的域名添加到信任列表中

02 配置request合法域名

  • 配置步骤:登陆微信小程序管理后台->开发->开发设置->服务器域名->修改request合法域名
  • 注意事项:
    • 域名只支持https协议
    • 域名不能使用ip地址或者localhost
    • 域名必须经过icp备案
    • 服务器域名一个月最多可以申请5次修改

03 发起get请求

  • 调用微信小程序提供wx.request()方法,可以发起get数据请求
wx.request({
    url: 'https://www.escook.cn/api/get',//请求的接口地址,必须基于https协议
    method: 'get', //请求的方式
    data:{ //发送到服务器的数据
        name: 'zs',
        age: 22
    },
    success: (res) => {//请求成功之后的回调函数
        console.log(res)//查看真实数据 console.log(res.data)
    }
})

04 发起post请求

wx.request({
    url: 'https://www.escook.cn/api/post',//请求的接口地址,必须基于https协议
    method: 'post', //请求的方式
    data:{ //发送到服务器的数据
        name: 'zs',
        age: 22
    },
    success: (res) => {//请求成功之后的回调函数
        console.log(res)//查看真实数据 console.log(res.data)
    }
})

05 页面刚加载时就请求数据

  • 在很多情况下,我们需要在页面刚加载的时候,自动请求一些初始化数据。此时需要在页面的onLoad事件中调用获取数据的函数,示例代码如下:
/**
* 生命周期函数——监听页面加载
*/
onLoad: function(options) {
    this.getInfo()
    this.postInfo()
}

06 跳过request合法域名校验

  • 开启开发环境不检验请求域名、TLS版本及HTTPS证书,跳过request合法域名的校验。

在这里插入图片描述

  • 注意:跳过合法域名校验,只在开发和测试阶段使用

07 跨域和Ajax

  • 跨域问题只存在于基于浏览器的web开发中。由于小程序的宿主环境不是浏览器,而是微信客户端,所以小程序中不存在跨域的问题。
  • Ajax技术的核心是依赖于浏览器中的XMLHttpRequest这个对象,由于小程序的宿主环境是微信客户端,所以小程序中不能叫做“发起Ajax请求”,而是叫做“发起网络数据请求”。

08 练习

在这里插入图片描述

  • app.json
{
  "pages":[
    "pages/home/home",
    "pages/message/message",
    "pages/contact/contact",
  ],
  "window":{
    "navigationBarBackgroundColor": "#025D54",
    "navigationBarTitleText": "在线测试",
    "navigationBarTextStyle":"white",
    
    "backgroundColor": "#efefef",
    "backgroundTextStyle":"dark",
    "onReachBottomDistance": 50
  },
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/home/home",
        "text": "home",
        "iconPath": "images/home.png",
        "selectedIconPath": "images/home-active.png"
      },
      {
        "pagePath": "pages/message/message",
        "text": "message",
        "iconPath": "images/message.png",
        "selectedIconPath": "images/message-active.png"
      },
      {
        "pagePath": "pages/contact/contact",
        "text": "contact",
        "iconPath": "images/contact.png",
        "selectedIconPath": "images/contact-active.png"
      }
    ]
  },
  
  "style": "v2",

  "sitemapLocation": "sitemap.json",

  "lazyCodeLoading": "requiredComponents"
  
}

  • wxml
<!-- 轮播图 -->
<swiper indicator-dots="true" circular="true">
    <swiper-item wx:for="{{swiperList}}" wx:key="id">
        <image src="{{item.image}}"></image>
    </swiper-item>
</swiper>

<!-- 九宫格 -->
<view class="grid-list">
    <view class="grid-item" wx:for="{{gridList}}" wx:key="id">
        <image src="{{item.icon}}"></image>
        <text>{{item.name}}</text>
    </view>
</view>

<!-- 图片展示 -->
<view class="img-box">
    <image src="/images/link-01.png" mode="widthFix"></image>
    <image src="/images/link-02.png" mode="widthFix"></image>
</view>

  • wxss
/* 轮播图 */
swiper {
    height: 350rpx;
}

swiper image {
    height: 100%;
    width: 100%;
}

/* 九宫格 */
.grid-list {
    display: flex;
    flex-wrap: wrap; /* 自动换行 */
    border-top: 1rpx solid #efefef ;
    border-left: 1rpx solid #efefef ;
}

.grid-item {
    width: 33.33%;
    height: 200rpx;
    display: flex;
    flex-direction: column; /* 纵向排列 */
    align-items: center; /* 居中对齐 */
    justify-content: center; /* 居中 */
    border-right: 1rpx solid #efefef ;
    border-bottom: 1rpx solid #efefef ;
    box-sizing: border-box;
}

.grid-item image {
    width: 60rpx;
    height: 60rpx;
}

.grid-item text {
    font-size: 24rpx;
    margin: 10rpx;
}

.img-box {
    display: flex;
    padding: 20rpx 10rpx;
    justify-content: space-around;
}

.img-box image {
    width: 45%;
}
  • js
// pages/home/home.js
Page({

    /**
     * 页面的初始数据
     */
    data: {
        //存放轮播图
        swiperList: [],
        //存放九宫格类别数据
        gridList: []
    },

    //获取轮播图地址
    getSwiperList(){
        wx.request({
          url: 'https://www.escook.cn/slides',
          method: 'GET',
          success: (res) => {
              console.log(res)
              this.setData({
                swiperList: res.data
              })
          }
        })
    },
    //获取九宫格类别数据
    getGridList() {
        wx.request({
          url: 'https://www.escook.cn/categories',
          method: 'GET',
          success: (res) => {
            console.log(res)
              this.setData({     
                  gridList: res.data
              })
          }
        })
    },
    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
        this.getSwiperList()
        this.getGridList()
    }
})
<think>好的,我现在需要回答用户关于如何在微信小程序中实现POST请求并通过CSRF安全检查的问题。首先,我需要理解用户的需求。他们想知道在小程序里发送POST请求时,如何防范CSRF攻击。根据提供的引用内容,特别是引用[2]中的例子,用户可能已经了解CSRF的基本原理,即攻击者诱导用户提交恶意请求。因此,我需要结合微信小程序的特性,给出具体的防护措施。 首先,我应该回顾CSRF的基本防护方法,常见的有使用CSRF Token和验证请求来源。然后,结合微信小程序的开发环境,考虑如何实施这些措施。例如,微信小程序的请求头中是否有特定的字段可以用来验证来源,或者如何生成和验证Token。 引用[1]提到PHP后端处理请求,可能涉及到Token的生成和验证。引用[3]讨论了数据加密和安全策略,可能和Token的安全性有关。此外,引用[2]中的例子展示了自动提交表单的CSRF攻击,所以需要防止这种未经授权的请求。 接下来,我需要分步骤说明实现方法: 1. **CSRF Token机制**:后端生成Token,并在小程序请求时发送给客户端。客户端在后续的POST请求中携带该Token,后端验证其有效性。需要注意Token的存储位置,比如小程序的全局变量或缓存中,同时要保证每个会话的Token唯一且一次性使用。 2. **验证请求来源**:微信小程序的请求头中包含Referer或自定义头,后端可以检查这些头信息是否来自可信的域名。但需要注意Referer可能被篡改,所以可能需要结合其他方法。 3. **利用微信的安全机制**:比如使用微信的登录态校验,结合session_key或openid来绑定用户会话,确保请求是经过用户授权的。 4. **加密和签名**:引用[3]提到数据加密,可能需要对请求参数进行签名,防止篡改。例如,使用HMAC对请求内容生成签名,后端验证签名是否正确。 5. **小程序端的实现**:在发送POST请求时,如何携带Token或其他验证信息。可能需要使用wx.request的header部分添加自定义头,如X-CSRF-Token。 同时,要考虑到小程序和Web应用的不同之处,比如小程序的运行环境更受控制,但依然需要防范CSRF。此外,引用[4]提到的Python/Django后端可能有内置的CSRF防护,需要确认是否与小程序兼容,或者需要如何调整。 可能的问题点:小程序默认的请求是否会自动携带cookie?如果依赖cookie来存储session,可能需要显式处理。但微信小程序的请求默认不携带cookie,所以可能需要使用其他方式传递session信息,比如在header中添加Authorization字段或自定义Token。 还需要考虑Token的存储安全,防止被恶意脚本获取。由于小程序运行在沙箱环境中,相对安全,但仍需避免将敏感信息存储在容易被访问的地方。 最后,需要给出示例代码,展示如何在小程序中发送带有CSRF Token的POST请求,以及后端(比如PHP或Django)如何验证这个Token。同时,提醒用户定期更新Token,使用HTTPS等增强安全性的措施。</think>在微信小程序中实现POST请求并通过CSRF(跨站请求伪造)防护,需要结合后端验证机制和小程序自身特性。以下是具体实现步骤: --- ### 一、CSRF防护核心机制 1. **CSRF Token验证** - **后端生成Token**:用户登录或初始化会话时,后端生成唯一且随机的CSRF Token,并将其返回给小程序(可通过登录接口响应或独立接口获取)[^1]。 - **客户端存储Token**:小程序将Token存储在全局变量(如`App.globalData`)或缓存(`wx.setStorageSync`)中。 - **请求携带Token**:在发送POST请求时,将Token添加到请求头(如`X-CSRF-Token`)或请求体参数中。 - **后端验证**:后端接收到请求后,比对Token与会话中存储的Token是否一致,若不一致则拒绝请求。 2. **同源验证** - 检查请求头中的`Referer`或自定义头(如`X-Requested-From`),确保请求来源为微信小程序可信域名[^3]。 - 示例(PHP验证Referer): ```php $allowed_domains = ['https://yourdomain.com']; if (!in_array($_SERVER['HTTP_REFERER'], $allowed_domains)) { die('非法请求来源'); } ``` --- ### 二、微信小程序实现步骤 1. **获取并存储CSRF Token** ```javascript // 小程序端:登录时获取Token wx.request({ url: 'https://api.example.com/login', method: 'POST', success(res) { App.globalData.csrfToken = res.data.csrf_token; // 存储Token } }); ``` 2. **发送POST请求时附加Token** ```javascript wx.request({ url: 'https://api.example.com/submit', method: 'POST', header: { 'X-CSRF-Token': App.globalData.csrfToken, // 通过Header传递 'Content-Type': 'application/json' }, data: { ... }, // 请求体数据 success() { ... } }); ``` 3. **后端验证逻辑(以PHP为例)** ```php session_start(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $clientToken = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? ''; if ($clientToken !== $_SESSION['csrf_token']) { http_response_code(403); echo json_encode(['error' => 'CSRF Token无效']); exit; } } ``` --- ### 三、增强安全性的补充措施 1. **Token绑定用户会话** 将Token与用户身份(如`openid`或`session_key`)关联,避免Token被跨会话复用[^3]。 2. **短期有效性** 设置Token过期时间(如10分钟),超时后需重新获取。 3. **HTTPS强制使用** 确保所有通信通过HTTPS加密,防止Token被中间人窃取。 4. **防重放攻击** 每个Token仅允许使用一次,或在关键操作(如支付)中增加验证码。 --- ### 四、示例:Django后端的CSRF适配 若使用Django框架,需调整默认的CSRF验证方式(因小程序无法直接使用Cookie): ```python # 视图函数中生成Token并返回 from django.middleware.csrf import get_token def get_csrf(request): return JsonResponse({'csrf_token': get_token(request)}) # 验证时通过Header读取Token from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie @csrf_exempt def submit_data(request): client_token = request.headers.get('X-CSRF-Token', '') if client_token != request.META.get('CSRF_COOKIE'): return HttpResponseForbidden() # 处理正常逻辑 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值