广告 JS SDK 跨域与安全合规开发

8 阅读6分钟

广告 JS SDK 跨域与安全合规开发

开发投放广告的 JS SDK 并支持百度、抖音等第三方接入,核心要解决 跨域请求合法性接口安全兼容性接入便捷性 四大问题。以下是需要做的具体调整,分为 SDK 前端封装服务端配置安全与合规 三大部分:

一、SDK 前端封装(核心:让第三方接入简单,且请求无跨域)

1. 封装跨域请求逻辑(兼容复杂请求)

广告接口(如获取广告素材、上报曝光 / 点击)通常是 POST 请求(需传递广告位 ID、用户设备信息等),且可能携带自定义头(如 X-AppId 用于验证第三方身份),属于 “复杂请求”,需确保请求格式符合服务端 CORS 配置。

// 广告SDK核心代码(your-ad-sdk.js)

class AdSDK {

  constructor(options) {

    // 第三方接入时必须传入的参数(用于安全验证)

    this.appId = options.appId; // 分配给百度/抖音的唯一标识

    this.adSlotId = options.adSlotId; // 第三方页面的广告位ID

    // 你的广告接口域名(必须是HTTPS)

    this.apiDomain = 'https://ad.yourcompany.com';

    // 配置请求头(需服务端CORS允许)

    this.headers = {

      'Content-Type': 'application/json',

      'X-AppId': this.appId, // 自定义头:用于服务端验证第三方身份

      'X-Sdk-Version': '1.0.0' // SDK版本,便于问题排查

    };

  }

  // 核心方法:请求广告素材

  async fetchAd() {

    try {

      const url = `${this.apiDomain}/api/ad/fetch`;

      const response = await fetch(url, {

        method: 'POST',

        headers: this.headers,

        body: JSON.stringify({

          adSlotId: this.adSlotId,

          // 可选:传递第三方页面的环境信息(需用户授权)

          pageUrl: window.location.href,

          userAgent: navigator.userAgent

        }),

        credentials: 'omit' // 广告SDK通常无需携带Cookie,避免跨域凭证问题

      });

      if (!response.ok) {

        // 区分跨域错误和业务错误(跨域错误时response.status可能为0)

        const errorMsg = response.status === 0

          ? '跨域请求失败,请检查服务端CORS配置'

          : `广告请求失败:${response.statusText}`;

        throw new Error(errorMsg);

      }

      const adData = await response.json();

      // 渲染广告(插入到第三方页面的广告位)

      this.renderAd(adData);

      return adData;

    } catch (error) {

      // 暴露错误给第三方(通过回调函数)

      if (this.options.onError) this.options.onError(error);

      console.error('AdSDK错误:', error);

    }

  }

  // 渲染广告到第三方页面

  renderAd(adData) {

    const adContainer = document.getElementById(this.options.containerId);

    if (!adContainer) {

      throw new Error('未找到广告容器,请检查containerId');

    }

    // 渲染逻辑(如插入图片/视频/HTML,避免样式冲突)

    adContainer.innerHTML = `

      <div class="your-ad-sdk-container"> <!-- 命名空间隔离样式 -->

        <a href="${adData.clickUrl}" target="_blank">

          <img src="${adData.imgUrl}" alt="${adData.title}">

        </a>

      </div>

    `;

    // 上报曝光事件

    this.reportImpression(adData.adId);

  }

  // 上报广告曝光(也是跨域请求)

  async reportImpression(adId) {

    await fetch(`${this.apiDomain}/api/ad/impression`, {

      method: 'POST',

      headers: this.headers,

      body: JSON.stringify({ adId, adSlotId: this.adSlotId })

    });

  }

}

// 暴露全局变量,方便第三方接入

window.AdSDK = AdSDK;
2. 接入便捷性优化(降低第三方接入成本)
  • 提供简单的初始化方式:第三方只需传入 appId、广告位 ID、容器 ID 即可。
<!-- 百度/抖音页面接入示例 -->

<div id="ad-container"></div> <!-- 广告容器 -->

<script src="https://sdk.yourcompany.com/your-ad-sdk.js"></script>

<script>

  // 初始化SDK(appId需向你申请)

  const adSdk = new AdSDK({

    appId: 'baidu-123456', // 百度的专属appId

    adSlotId: 'baidu-homepage-banner', // 百度页面的广告位ID

    containerId: 'ad-container', // 广告渲染的容器ID

    onError: (error) => { console.log('广告加载失败:', error); } // 错误回调

  });

  // 加载广告

  adSdk.fetchAd();

</script>
  • 异步加载 SDK:允许第三方通过 async 加载,避免阻塞页面。
<script async src="https://sdk.yourcompany.com/your-ad-sdk.js" onload="initAdSdk()"></script>
  • 样式隔离:广告 DOM 使用独立类名(如 your-ad-sdk-xxx),避免与第三方页面的 CSS 冲突。

二、服务端配置(核心:确保跨域请求合法,接口安全)

1. 跨域配置(CORS):允许百度、抖音域名访问

服务端必须配置 CORS 响应头,明确允许第三方域名(如百度 https://www.baidu.com、抖音 https://www.douyin.com)的跨域请求,同时处理预检请求(OPTIONS)。

Node.js + Express 为例:

const express = require('express');

const app = express();

app.use(express.json());

// 允许的第三方域名白名单(提前与百度、抖音确认其实际域名)

const ALLOWED_ORIGINS = [

  'https://www.baidu.com',

  'https://baidu.com',

  'https://www.douyin.com',

  'https://douyin.com'

];

// CORS中间件

app.use((req, res, next) => {

  const origin = req.headers.origin;

  // 只允许白名单内的域名跨域

  if (ALLOWED_ORIGINS.includes(origin)) {

    res.setHeader('Access-Control-Allow-Origin', origin);

  }

  // 允许的请求方法(广告SDK用POST,需包含OPTIONS预检)

  res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');

  // 允许的请求头(需包含SDK中自定义的X-AppId等)

  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-AppId, X-Sdk-Version');

  // 广告SDK通常无需携带Cookie,关闭credentials

  res.setHeader('Access-Control-Allow-Credentials', 'false');

  // 预检结果缓存1小时(3600秒),减少重复预检

  res.setHeader('Access-Control-Max-Age', '3600');

  // 处理预检请求(OPTIONS)

  if (req.method === 'OPTIONS') {

    return res.sendStatus(204); // 无需返回body

  }

  next();

});

// 广告接口:获取广告素材

app.post('/api/ad/fetch', (req, res) => {

  const { appId, adSlotId } = req.body;

  // 验证appId合法性(防止恶意调用)

  if (!verifyAppId(appId)) {

    return res.status(403).json({ code: 403, msg: '无效的appId' });

  }

  // 业务逻辑:根据adSlotId返回对应的广告素材

  const adData = getAdBySlotId(adSlotId); // 自定义函数:从数据库查询广告

  res.json({ code: 200, data: adData });

});

// 启动服务(必须用HTTPS,否则第三方HTTPS页面会拦截)

const https = require('https');

const fs = require('fs');

const options = {

  key: fs.readFileSync('your-ssl-key.pem'),

  cert: fs.readFileSync('your-ssl-cert.pem')

};

https.createServer(options, app).listen(443, () => {

  console.log('广告服务启动:https://ad.yourcompany.com');

});
2. 接口安全加固(防止滥用和攻击)
  • appId 验证:为百度、抖音分配唯一 appId,服务端校验 X-AppId 头,拒绝无效 appId 的请求(防止其他网站盗用 SDK)。

  • 请求频率限制:对每个 appId 限制每秒请求次数(如 100 次 / 秒),防止 DDoS 攻击。

// 伪代码:使用redis记录请求次数

const rateLimit = (req, res, next) => {

  const appId = req.headers['x-appid'];

  const key = `rate_limit:${appId}`;

  redis.incr(key, (err, count) => {

    if (count === 1) redis.expire(key, 1); // 1秒过期

    if (count > 100) { // 超过100次/秒

      return res.status(429).json({ msg: '请求过于频繁' });

    }

    next();

  });

};

app.use('/api/ad', rateLimit); // 对广告接口应用限流
  • 广告素材域名白名单:广告图片 / 视频的 URL 域名(如 https://img.yourcompany.com)需配置 CORS,允许第三方域名加载(否则图片可能无法显示)。

三、安全与合规(避免第三方平台拒绝接入)

1. 必须使用 HTTPS
  • 百度、抖音等正规平台的页面都是 HTTPS,若你的 SDK 或广告接口用 HTTP,会被浏览器拦截(混合内容错误),导致广告无法加载。

  • 申请可信 CA 证书(如 Let’s Encrypt 免费证书),确保 sdk.yourcompany.com(SDK 地址)和 ad.yourcompany.com(接口地址)均为 HTTPS。

2. 隐私合规(关键!否则可能被下架)
  • 用户数据收集限制:SDK 仅收集必要信息(如广告位 ID、页面 URL),禁止收集敏感信息(如用户 Cookie、地理位置),除非第三方已获得用户授权。

  • 提供合规文档:向百度、抖音提供《SDK 隐私政策》,说明数据收集目的、方式,承诺不滥用数据(符合 GDPR、国内《个人信息保护法》)。

  • 可选:支持隐私开关:允许第三方通过配置关闭数据收集(如 { collectData: false })。

3. 广告内容合规
  • 广告素材需符合第三方平台的规范(如百度禁止虚假广告,抖音禁止低俗内容),避免 SDK 被第三方封禁。

  • 提供广告审核机制,确保返回给第三方的广告内容合法。

四、测试与接入支持

  • 提供测试环境:给百度、抖音提供测试 appId 和测试接口(https://test-ad.yourcompany.com),方便其联调。

  • 错误排查工具:SDK 中添加详细日志(如 console.log('[AdSDK] 开始请求广告...')),服务端记录请求日志(包含 appIdadSlotId、错误原因),便于快速定位跨域或业务问题。

  • 接入文档:明确说明 appId 申请流程、初始化参数、错误码含义(如 403 表示 appId 无效,500 表示服务端错误)。

总结

核心调整围绕 “跨域合法”“安全合规”

  1. 前端 SDK 封装跨域请求,简化接入;

  2. 服务端配置精准的 CORS 白名单,处理预检请求,并用 HTTPS;

  3. 通过 appId 验证、限流确保接口安全;

  4. 遵守隐私和广告内容规范,避免第三方平台拒绝接入。

这样百度、抖音等第三方接入时,只需简单配置即可加载广告,且无跨域或安全风险。