家明故事

微信网页授权CORS问题解决方案

家明 0 0

你在微信网页授权中遇到的CORS预检请求被重定向阻塞的问题,通常是因为服务器未能正确响应浏览器的OPTIONS预检请求。下面我将为你提供一些PHP服务器端的修复示例。

🛠️ 微信网页授权CORS问题的PHP服务器端修复

当你的PHP后端遇到CORS预检请求问题时,核心解决方案是确保服务器正确响应OPTIONS请求并设置适当的CORS头部。以下是详细的修复方案:

1. 基础CORS处理示例

创建一个基础的CORS处理脚本,可以在所有API接口调用前执行:

php
<?php
// 允许所有源访问(生产环境应改为具体域名)
header("Access-Control-Allow-Origin: *");
// 允许的请求方法
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
// 允许的请求头
header("Access-Control-Allow-Headers: Origin, Content-Type, X-Requested-With, Accept, Authorization");
// 是否允许发送Cookie
header("Access-Control-Allow-Credentials: true");
// 预检请求缓存时间(秒)
header("Access-Control-Max-Age: 3600");

// 如果是OPTIONS请求(预检请求),直接返回成功
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    http_response_code(200);
    exit();
}

// 你的后续PHP代码...
?>

2. 更安全的CORS处理类

对于更复杂的应用,可以创建一个CORS处理类:

php
<?php
class CORSHandler {
    private $allowedOrigins = [];
    private $allowedMethods = ['GET', 'POST', 'OPTIONS'];
    private $allowedHeaders = ['Content-Type', 'Authorization'];
    
    public function __construct($origins = []) {
        $this->allowedOrigins = $origins;
    }
    
    public function handle() {
        $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
        
        // 检查来源是否允许
        if (!empty($this->allowedOrigins)) {
            if (in_array($origin, $this->allowedOrigins)) {
                header("Access-Control-Allow-Origin: $origin");
            } elseif (in_array('*', $this->allowedOrigins)) {
                header("Access-Control-Allow-Origin: *");
            }
        } else {
            header("Access-Control-Allow-Origin: *");
        }
        
        header("Access-Control-Allow-Methods: " . implode(', ', $this->allowedMethods));
        header("Access-Control-Allow-Headers: " . implode(', ', $this->allowedHeaders));
        header("Access-Control-Allow-Credentials: true");
        header("Access-Control-Max-Age: 3600");
        
        // 直接返回OPTIONS请求
        if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
            http_response_code(200);
            exit();
        }
    }
}

// 使用示例
$cors = new CORSHandler([
    'https://yourdomain.com',
    'https://yourotherdomain.com'
    // 生产环境不要使用通配符*
]);
$cors->handle();

// 你的应用代码继续 here...
?>

3. 微信授权回调接口完整示例

以下是一个处理微信网页授权的完整示例,包含CORS支持:

php
<?php
// 设置CORS头部
header("Access-Control-Allow-Origin: https://yourfrontend.com"); // 替换为你的前端域名
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 3600");

// 处理预检请求
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    http_response_code(200);
    exit();
}

// 处理微信授权回调
if ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_GET['code'])) {
    $code = $_GET['code'];
    $appid = '你的微信公众号APPID';
    $secret = '你的微信公众号SECRET';
    
    // 通过code获取access_token
    $token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code=$code&grant_type=authorization_code";
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $token_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    // 解决可能的curl响应慢问题,可考虑DNS预解析或hosts绑定:cite[8]
    $response = curl_exec($ch);
    curl_close($ch);
    
    $token_data = json_decode($response, true);
    
    if (isset($token_data['errcode'])) {
        // 处理错误
        http_response_code(400);
        echo json_encode([
            'error' => '微信授权失败',
            'message' => $token_data['errmsg']
        ]);
        exit();
    }
    
    // 获取用户信息
    $access_token = $token_data['access_token'];
    $openid = $token_data['openid'];
    $user_info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN";
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $user_info_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $user_response = curl_exec($ch);
    curl_close($ch);
    
    $user_data = json_decode($user_response, true);
    
    // 返回用户信息给前端
    header('Content-Type: application/json');
    echo json_encode([
        'success' => true,
        'user' => $user_data
    ]);
    exit();
}

// 其他请求处理...
?>

4. 使用.htaccess配置CORS(Apache服务器)

如果使用Apache服务器,可以在.htaccess文件中配置:

apacheconf
<IfModule mod_headers.c>
    # 允许的源域
    Header always set Access-Control-Allow-Origin "https://yourfrontend.com"
    # 允许的请求方法
    Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
    # 允许的请求头
    Header always set Access-Control-Allow-Headers "Origin, Content-Type, X-Requested-With, Accept, Authorization"
    # 允许携带凭证
    Header always set Access-Control-Allow-Credentials "true"
    # 预检请求缓存
    Header always set Access-Control-Max-Age "3600"
    
    # 针对OPTIONS请求直接返回200
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} OPTIONS
    RewriteRule ^(.*)$ $1 [R=200,L]
</IfModule>

5. Nginx服务器配置

如果你使用Nginx服务器,可以在配置文件中添加:

nginx
location / {
    # 处理预检请求
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' 'https://yourfrontend.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Authorization';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 3600;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
    }
    
    # 其他请求的CORS头
    add_header 'Access-Control-Allow-Origin' 'https://yourfrontend.com';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Authorization';
    add_header 'Access-Control-Allow-Credentials' 'true';
}

6. 微信网页授权注意事项

  1. 回调域名配置:确保在微信公众平台正确配置了授权回调域名,这个域名必须与你的实际域名完全一致

  2. 避免多次重定向:微信授权流程本身涉及重定向,确保你的服务器不会在预检请求上再次重定向。

  3. Session和Cookie处理:如果涉及会话保持,确保正确设置Cookie的SameSite属性

    php
    ini_set('session.cookie_samesite', 'None');
    ini_set('session.cookie_secure', '1');

📋 总结表格

问题场景解决方案代码示例/配置
基础CORS支持设置CORS头部并处理OPTIONS请求header("Access-Control-Allow-Origin: https://yourdomain.com");
多域名支持动态检查Origin并设置相应头部CORSHandler类示例
微信授权回调接口正确处理预检请求和实际授权请求完整微信授权示例代码
Apache服务器配置通过.htaccess文件设置CORS头部Header always set Access-Control-Allow-Origin "https://yourdomain.com"
Nginx服务器配置在服务器配置中处理OPTIONS请求和设置CORS头部if ($request_method = 'OPTIONS') { return 204; }
生产环境安全考虑限制允许的源域,避免使用通配符*使用具体域名而非*

以上解决方案应该能帮助你解决微信网页授权中的CORS预检请求问题。根据你的服务器环境和具体需求,选择适合的方案进行实施。如果问题仍然存在,可能需要进一步检查网络环境、服务器配置和微信开放平台的相关设置。

标签:微信网页授权  CORS  

打赏

上一篇:PHP实现微信网页授权跳转

下一篇:没有了

发表评论