在将php zend应用迁移至aws ec2后,用户常遇到“the form submitted did not originate from the expected site”错误,尤其在登录时。此问题通常与跨站请求伪造(csrf)保护机制对请求来源的验证失败有关。本文将深入分析其原因,并提供通过强制使用https协议来有效解决此问题的专业指南。
深入理解“非预期来源”错误及其根源
当PHP应用程序在AWS EC2环境中出现“The form submitted did not originate from the expected site”错误时,这通常是应用程序内置的跨站请求伪造(CSRF)保护机制被触发的结果。CSRF保护旨在确保表单提交请求确实来源于用户当前正在访问的网站,而非恶意第三方站点。它通常通过验证请求的Origin或Referer头部信息,或通过比对会话中存储的CSRF令牌来实现。
在迁移Web应用到云环境(如AWS EC2)时,特别是当涉及到协议变更(从HTTP到HTTPS)或引入负载均衡器/反向代理时,这个错误尤为常见。其核心原因在于,应用程序对请求协议或来源的判断与实际情况不符,导致CSRF验证失败:
协议不一致性: 最常见的情况是,应用程序在内部生成链接或验证请求时,期望使用HTTPS协议,但由于某种原因(例如,通过HTTP访问负载均衡器,再由负载均衡器转发到后端EC2实例的HTTP端口),应用程序接收到的请求被认为是HTTP协议。这种协议上的不匹配会使得Origin或Referer头部在应用程序看来是“不信任”的,或者与预期不符。负载均衡器/反向代理的影响: 在AWS EC2架构中,通常会在前端部署Application Load Balancer (ALB) 或 Network Load Balancer (NLB)。用户通过HTTPS访问ALB,ALB再通过HTTP(或HTTPS)将请求转发到后端的EC2实例。如果应用程序没有正确配置来识别ALB转发的原始协议(通常通过X-Forwarded-Proto等头部),它可能会误认为请求是通过HTTP接收的。会话cookie安全标志: 如果应用程序在HTTPS环境下设置了带有Secure标志的会话cookie,但后续请求尝试通过HTTP发送,浏览器将拒绝发送该cookie,导致会话丢失,进而影响CSRF令牌的验证。解决方案:强制使用HTTPS协议
根据经验,将网站的访问协议从HTTP完全切换到HTTPS,并确保整个请求链路都使用HTTPS,是解决此问题的最有效方法。这不仅能解决CSRF验证问题,还能显著提升网站的安全性。
1. 配置AWS负载均衡器(ALB/NLB)以终止HTTPS
这是在AWS上部署Web应用时推荐的最佳实践。
立即学习“PHP免费学习笔记(深入)”;
步骤一:获取SSL证书。在AWS Certificate Manager (ACM) 中申请或导入您的SSL/TLS证书。ACM可以免费为AWS资源(如ALB)提供证书。步骤二:配置ALB监听器。在您的ALB上,添加一个HTTPS (端口443) 监听器。将该监听器配置为使用您在ACM中获取的证书。步骤三:配置ALB目标组。将您的EC2实例注册到ALB的目标组中。目标组的协议可以设置为HTTP(端口80)或HTTPS(端口443),取决于您的EC2实例上的Web服务器配置。推荐做法:ALB终止HTTPS,后端EC2使用HTTP。 这种方式可以减轻EC2实例的SSL/TLS加密解密负担。在这种情况下,ALB会将原始协议信息通过X-Forwarded-Proto头部传递给后端实例。ALB与后端EC2均使用HTTPS。 如果您的安全策略要求端到端加密,ALB可以配置为使用HTTPS转发到后端EC2实例的HTTPS端口。示例:ALB配置(伪代码/概念)
// ALB Listener Configuration for HTTPS (Port 443){ "Protocol": "HTTPS", "Port": 443, "Certificates": [ { "CertificateArn": "arn:aws:acm:REGION:ACCOUNT_ID:certificate/YOUR_ACM_CERT_ID" } ], "DefaultActions": [ { "Type": "forward", "TargetGroupArn": "arn:aws:elasticloadbalancing:REGION:ACCOUNT_ID:targetgroup/YOUR_TARGET_GROUP_NAME" } ]}// Target Group Configuration (e.g., HTTP to backend){ "Protocol": "HTTP", "Port": 80, // Or 443 if backend also uses HTTPS "VpcId": "vpc-YOUR_VPC_ID", "HealthCheckProtocol": "HTTP", "HealthCheckPort": "traffic-port"}登录后复制
2. 配置EC2实例上的Web服务器(以Apache为例)
如果您的Web服务器直接暴露在公网(不推荐用于生产环境,除非有特定需求),或者您希望ALB到EC2实例之间也强制使用HTTPS,则需要在EC2实例上配置Web服务器。

AI应用商店,提供即时交付、按需付费的人工智能应用服务


步骤一:安装mod_ssl (Apache HTTP Server)。
sudo yum install mod_ssl # CentOS/RHELsudo apt-get install libapache2-mod-ssl # Debian/Ubuntu登录后复制
步骤二:获取SSL证书。您可以使用Let's Encrypt通过Certbot工具获取免费的SSL证书。
sudo yum install epel-releasesudo yum install certbot python3-certbot-apache # CentOS/RHELsudo apt-get install certbot python3-certbot-apache # Debian/Ubuntusudo certbot --apache -d yourdomain.com -d www.yourdomain.com登录后复制
Certbot会自动配置Apache的SSL虚拟主机。
步骤三:配置Apache虚拟主机。确保您的Apache配置(通常在/etc/httpd/conf.d/ssl.conf或/etc/apache2/sites-available/default-ssl.conf)正确指向您的SSL证书和私钥。
<VirtualHost *:443> ServerName yourdomain.com documentRoot /var/www/html/your_php_app SSLEngine on SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem # 其他配置,如日志、目录权限等 <Directory /var/www/html/your_php_app> AllowOverride All Require all granted </Directory></VirtualHost># 可选:将所有HTTP请求重定向到HTTPS<VirtualHost *:80> ServerName yourdomain.com Redirect permanent / https://yourdomain.com/</VirtualHost>登录后复制
步骤四:重启Apache服务。
sudo systemctl restart httpd # CentOS/RHELsudo systemctl restart apache2 # Debian/Ubuntu登录后复制
3. PHP应用程序层面的调整
如果您的应用程序位于负载均衡器之后,并且负载均衡器将HTTPS请求转发为HTTP到后端,那么应用程序可能需要感知到原始请求是HTTPS。
检测X-Forwarded-Proto头部:大多数PHP框架(如Zend framework)都提供了识别代理协议的机制。您可以在应用程序的入口文件(如public/index.php)或配置中,根据X-Forwarded-Proto头部来判断当前请求的真实协议。
// 示例:在Zend framework中,可能需要确保URL生成器知道当前协议// 这通常由框架自动处理,但如果遇到问题,可以手动检查if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { $_SERVER['HTTPS'] = 'on'; // 欺骗PHP认为请求是HTTPS}// 或者在Zend的配置中设置 trusted_proxies// config/autoload/global.php 或 local.php登录后复制
确保cookie的Secure标志:当网站完全运行在HTTPS上时,确保会话cookie设置了Secure标志。这指示浏览器只在HTTPS连接上发送此cookie,增强安全性。PHP的session.cookie_secure配置项应设置为true。
// php.ini 或 .htaccesssession.cookie_secure = 1// 或者在代码中ini_set('session.cookie_secure', 1);登录后复制
注意事项与最佳实践
清除浏览器缓存和cookie: 在进行协议更改后,务必让用户清除浏览器缓存和cookie,以确保新的会话和CSRF令牌能够正确生成和处理。监控和日志: 密切关注Web服务器和应用程序日志,以便在出现问题时快速定位。安全性: 始终将HTTPS作为生产环境的强制要求。它不仅解决了CSRF问题,还保护了数据传输的完整性和机密性。性能: 使用AWS ALB终止SSL/TLS可以减轻EC2实例的CPU负担,提高整体性能。HSTS (HTTP Strict Transport Security): 考虑启用HSTS头部,强制浏览器在后续访问中始终使用HTTPS,即使用户输入的是HTTP URL。# Apache配置<IfModule mod_headers.c> Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"</IfModule>登录后复制
总结
“The form submitted did not originate from the expected site”错误在PHP应用迁移到AWS EC2时是一个常见但可解决的问题。其根本原因在于CSRF保护机制对请求来源或协议的误判。通过强制使用HTTPS协议,无论是通过AWS负载均衡器终止SSL,还是直接在EC2实例的Web服务器上配置HTTPS,都能有效解决协议不一致性导致的问题,确保CSRF验证机制正常工作。结合应用程序层面的适当调整和遵循最佳实践,可以构建一个既安全又稳定的Web环境。
以上就是解决EC2上PHP应用表单提交“非预期来源”错误:HTTPS协议配置指南的详细内容,更多请关注php中文网其它相关文章!