僅檢測 `User-Agent` 包含 `MicroMessenger` 存在誤判風險:
function isWechatUA() {
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
return stripos($ua, 'MicroMessenger') !== false;
}
微信內嵌瀏覽器會注入 `WeixinJSBridge` 對象,外部瀏覽器無此對象。
<script>
function checkWeixinJSBridge() {
if (typeof WeixinJSBridge !== 'undefined') {
// 確認為微信環境
fetch('/api/wechat/verify', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({verified: true})
});
} else {
// 非微信,可選:提示用戶、跳轉下載頁
document.body.innerHTML = '<div style="padding:20px;text-align:center">請在微信中打開</div>';
}
}
// 微信 JSBridge 就緒事件
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', checkWeixinJSBridge, false);
} else if (document.attachEvent) {
document.attachEvent('onWeixinJSBridgeReady', checkWeixinJSBridge);
}
// 兼容舊版:直接檢查
setTimeout(checkWeixinJSBridge, 100);
</script>
// /api/wechat/verify
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
if (isset($data['verified']) && $data['verified'] === true) {
$_SESSION['wechat_verified'] = true;
echo json_encode(['success' => true]);
} else {
http_response_code(400);
}
}
session_start();
// 1. UA 預檢
if (!isWechatUA()) {
// 可選:記錄日誌、返回 403
header('HTTP/1.1 403 Forbidden');
exit('非微信環境禁止訪問 (UA)');
}
// 2. Session 驗證 (JS 回調已設置)
if (!isset($_SESSION['wechat_verified'])) {
// 首次訪問,輸出包含 JSBridge 檢測腳本的「加載中」頁
echo '<!DOCTYPE html><html><head><meta charset="utf-8"><title>加載中...</title></head><body>玩命加載中...<script src="/static/js/wechat_verify.js"></script></body></html>';
exit;
}
// 3. 雙重通過,輸出真實業務內容
// ... 正常業務邏輯 ...
若需獲取用戶 OpenID/UnionID,必須走 OAuth2.0 授權碼模式:
此流程天然驗證微信環境,無需額外 UA/JSBridge 判斷。
| 方案 | 可靠性 | 成本 | 適用場景 |
|---|---|---|---|
| UA 判斷 | 低 (可偽造、漏判) | 極低 | 簡單頁面、非核心業務 |
| UA + JSBridge | 高 (難偽造 JSBridge) | 低 (前端 JS + 後端 Session) | 大多數 H5 頁面、營銷活動 |
| OAuth2.0 授權 | 最高 (微信官方驗證) | 中 (需配置回調域名、存儲 token) | 需獲取用戶身份、支付、核心業務 |
根據業務安全等級選擇方案,「UA + JSBridge」性價比最高,「OAuth2.0」最權威。