王新阳

wangxinyang

解决$GLOBALS["HTTP_RAW_POST_DATA"]获取不到数据的问题

转自hpugym的CSDN:https://blog.csdn.net/hpugym/article/details/54969457

昨天在微信中公众号开发中使用$GLOBALS["HTTP_RAW_POST_DATA"]来获取微信公众平台推送过来的post数据,结果惊奇的发现微信号总是提示“该微信公众号暂时无法提供服务”,仔细去检查代码,也没错,可就是无法提供服务。今天又检查了一把,还是没有语法错误,于是乎,我将中间的所有数据全部写到的记事本里去,通过及时本发现$GLOBALS["HTTP_RAW_POST_DATA"]获取的数据是空的。经过资料查找,终于发现了解决的套路:

$GLOBALS ["HTTP_RAW_POST_DATA"]跟$_POST,file_get_contents('php://input') 差不多,用$GLOBALS ["HTTP_RAW_POST_DATA"]或file_get_contents('php://input')的情况大多是为了获取$_POST无法接收的数据类型(如XML数据)

在$GLOBALS ["HTTP_RAW_POST_DATA"]取不到值的情况下可以按以下方式排查:
1、用file_get_contents('php://input')获取数据。如果获取不到,则可能是数据传输错误,对请求进行捉包,分析数据。
2、如果file_get_contents('php://input')有数据。则查看php.ini配置文件。

找到如下,如果没开启则开启

always_populate_raw_post_data = On

注意:这种处理方式是在php版本较低的时候,在php-ini中才有的配置,当版本升级到7,或者更高的时候该机制就被废弃掉了。

下边归纳几种php获取post数据的方式:

RPC 规定接收取值方式 $GLOBALS['HTTP_RAW_POST_DATA'];
PHP默认识别的数据类型是application/x-www.form-urlencoded标准的数据类型。

1、$_POST['paramName']
只能接收Content-Type: application/x-www-form-urlencoded提交的数据,php会将http请求body相应数据会 填入到数组$_POST,填入到$_POST数组中的数据是进行urldecode()解析的结果。(其实,除了该Content-Type,还有 multipart/form-data表示数据是表单数据)

2、file_get_contents("php://input")
适用大多数类型的Content-type,php://input 允许读取 POST 的原始数据。和 $HTTP_RAW_POST_DATA 比起来,它给内存带来的压力较小,并且不需要任何特殊的 php.ini 设置。php://input 不能用于 enctype="multipart/form-data"。

3、$GLOBALS['HTTP_RAW_POST_DATA'];
总是产生 $HTTP_RAW_POST_DATA  变量包含有原始的 POST 数据。此变量仅在碰到未识别 MIME 类型的数据时产生。$HTTP_RAW_POST_DATA  对于 enctype="multipart/form-data"  表单数据不可用。

如果post过来的数据不是PHP能够识别的,你可以用 $GLOBALS['HTTP_RAW_POST_DATA']来接收,比如 text/xml 或者 soap 等等。需要设置php.ini中的always_populate_raw_post_data值为On,PHP才会总把POST数据填入变量$http_raw_post_data。

1,Coentent-Type仅在取值为application/x-www-data-urlencoded和multipart/form- data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量$_POST
2,PHP不能识别的Content-Type类型的时候,会将http请求包中相应的数据填入变量$HTTP_RAW_POST_DATA
3, 只有Coentent-Type不为multipart/form-data的时候,PHP不会将http请求数据包中的相应数据填入php: //input,否则其它情况都会。填入的长度,由Coentent-Length指定。
4,只有Content-Type为application/x-www-data-urlencoded时,php://input数据才 跟$_POST数据相一致。
5,php://input数据总是跟$HTTP_RAW_POST_DATA相同,但是php://input 比$HTTP_RAW_POST_DATA更凑效,且不需要特殊设置php.ini
6,PHP会将PATH字段的query_path部分,填入全局变量$_GET。通常情况下,GET方法提交的http请求,body为空。

总之:
1、如果是 application/x-www-form-urlencoded 和 multipart/form-data 格式 用 $_POST;
2、如果不能获取的时候比如 text/xml、application/json、soap,使用 file_get_contents('php://input');

curl: (35) Unknown SSL protocol error in connection to abc.com:443

curl: (35) Unknown SSL protocol error in connection to abc.com:443

出现此错误可能的原因:

1、PHP版本过低,我从php5.6升级到php7.2

2、对于访问https链接,添加跳过验证对等证书和域名

if(strpos(strtolower($url), 'https://')===0){
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //https请求时跳过cURL验证对等证书
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //https请求时跳过cURL验证域名
}


http访问跳转至https

网站安装SSL证书后,未https访问根据端口判断,并自动转至https

if($_SERVER['SERVER_PORT']=='80'){
    header("Location: https://www.abc.com".$_SERVER['REQUEST_URI']);
    exit;
}

增加对域名的判断

switch(strtolower($_SERVER['SERVER_NAME'])){
    case 'abc.com':
        if($_SERVER['SERVER_PORT']=='80'){
            header("Location: https://www.abc.com".$_SERVER['REQUEST_URI']);
            exit;
        }
        break;
}

对是否为https方式访问的判断,不能单纯靠 $_SERVER['SERVER_PORT']=='80
建议方法:

function is_https() {
	if(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT']==='443'){
		return true;
	}elseif( !empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off'){
		return true;
	}elseif( !empty($_SERVER['HTTP_FROM_HTTPS']) && strtolower($_SERVER['HTTP_FROM_HTTPS']) !== 'off'){ //西部数码
		return true;
	}else{
		return false;
	}
}

使用.htaccess重定向

RewriteEngine On
RewriteCond %{HTTP:From-Https} !^on$ [NC]
RewriteCond %{HTTP_HOST} ^(www.)?abc.com$ [NC]
RewriteRule ^(.*)$ https://www.abc.com/$1 [R=301,L]


PHP进制转换

常见的进制:
二进制      binary -->  bin
八进制      octal   -->  oct
十进制      decimal -->  dec
十六进制   hexadecimal -->  hex

记住上表,不同进制间转换只需两个缩写相连即为对应函数。如十进制转二进制为 decbin($num)

在任意进制之间转换数字
string base_convert ( string $number , int $frombase , int $tobase )

返回一字符串,把 number 以 tobase 进制的表示。number 本身的进制由 frombase 指定。frombase 和 tobase 都只能在 2 和 36 之间(包括 2 和 36)。高于十进制的数字用字母 a-z 表示,例如 a 表示 10,b 表示 11 以及 z 表示 35。

如十进制转五进制:base_convert($hexadecimal, 10, 5);

PHP根据文件头获取文件类型

<?php
$file = 'https://www.baidu.com/img/baidu_logo.gif';
$fp = fopen($file, 'rb');
if(! $fp)exit('failed');

//$content = stream_get_contents($fp); //全部读取
/* 循环读取
while(! feof($fp)){
	$content .= fread($fp, 10240);
}
*/
$content = fread($fp, 2);
fclose($fp);
$arr = unpack('C2chars', $content);
print_r($arr);
?>

根据上面方法可获取文件头前两个字节的十进制数字,再用dcehex()转为十六进制,然后与 文件头大全对照,即可获取文件类型。

CodeIgniter把找不到的页面301跳转到指定页

问题:网站改版后页面链接地址发生变化,百度收录的原内容打开后出现404。

解决办法:

1、如果原网站也是 /product/view/id/12.html 这样的访问方式,只需要在自定义路由中设置下即可。如 $route['product/view/id/(:any)']='new_product/new_list';  把原产品详情页路由到新产品列表页;可以全部路由到一个新控制器,然后再跳转。

2、如果原网站是 product.asp?id=12 这种而新网站又是linux不支持asp时,可以使用 .htaccess 直接进行301跳转。

RewriteRule ^(news)\.asp$ http://domain/$1/gongsixinwen.html [R=301,L]
RewriteRule ^(products)\.asp$ http://domain/$1/jixie.html [R=301,L]

3、跳转到一个单独的控制器再进行精确跳转。

RewriteRule ^(news|art|files)\/ https://domain/baidu/index/$1 [R=301,L]


PHPMailer发信需要的函数

php_openssl(如果使用SSL加密发送)、php_sockets、fsockopen

今天本地电脑使用PHPMailer发送邮件成功,上传到阿里云主机后发送失败,原来阿里云主机默认未开启 fsockopen 函数,到主机控制面板中 站点信息》高级环境设置》PHP.ini设置 中启用即可。

因网站漏洞被上传木马的解决方法

网站被上传木马,导致页面被植入恶意链接,如果找不到漏洞,可以用 .htaccess 或 web.config 屏蔽木马程序的运行,确保网站的"相对"安全。

.htaccess

RewriteEngine on
RewriteRule (uploadfile.+\.(php|asp|aspx|jsp))$ /rec.php?uri=$1 [R,NC,L]

web.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="规则 1" stopProcessing="true">
                    <match url="(uploadfile.+\.(php|asp|aspx|jsp))$" />
                    <action type="Redirect" url="/rec.php?uri={R:1}" appendQueryString="false" redirectType="Found" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

上面规则是阻止上传文件目录 uploadfile 中 php/asp/aspx/jsp 等类型文件的运行,并跳转到 /rec.php 进行记录(也可以重定向到百度……)。虽然没有解决漏洞,至少确保了木马文件不能运行。

CodeIgniter框架中网站英文版以 /en/index.php 方式访问的设置

网址: http://www.baidu.com/en/about.html
实际请求地址: /en/index.php/about

实现步骤:

一、新建 /en 文件夹,把原 index.php 复制进来, 修改以下内容:
 1、 $system_path = '../system';
 2、 $application_folder = '../application/en_web';
 3、define('FCPATH', realpath(dirname(__FILE__).'/../').DIRECTORY_SEPARATOR);

二、在 /application 目录下新建英文版app的文件夹 en_web,把原中文版的app内容复制进来,修改 config.php
 1、$config['index_page'] = 'en/';

三、修改 .htaccess 文件,在原内容前面添加:
    RewriteRule ^en\/(.*)$ en/index.php/$1 [L]

OK!
另外,可以在 /index.php 中使用 $_SERVER['HTTP_ACCEPT_LANGUAGE'] 判断客户语言并自动转入相应版本。

附我的 .htaccess

RewriteEngine On

RewriteRule ^en\/m\.php(.*)$ en/m.php/$1 [L]
RewriteRule ^en\/manage\.php(.*)$ en/manage.php/$1 [L]
RewriteRule ^en\/(.*)$ en/index.php/$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^.+\.(ico|js|css|jpg|jpe|jpeg|png|bmp|gif|mp4|flv|swf|txt|pdf|zip|rar|htm|doc|docx|xls|xlsx)$
RewriteRule ^(.*)$ index.php/$1 [L]

PHP关于获取真实IP的方法

$_SERVER["REMOTE_ADDR"]
$_SERVER["HTTP_X_FORWARDED_FOR"]

一、没有使用代理服务器的PHP获取客户端IP情况:
REMOTE_ADDR = 客户端IP
HTTP_X_FORWARDED_FOR = 没数值或不显示

二、使用透明代理服务器的情况:Transparent Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 客户端真实 IP (经过多个代理服务器时,这个值类似:221.5.252.160, 203.98.182.163, 203.129.72.215)
这类代理服务器还是将客户端真实的IP发送给了访问对象,无法达到隐藏真实身份的目的.

三、使用普通匿名代理服务器的PHP获取客户端IP情况:Anonymous Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP (经过多个代理服务器时,这个值类似:203.98.182.163, 203.98.182.163, 203.129.72.215)
这种情况下隐藏了客户端的真实IP,但是向访问对象透露了客户端是使用代理服务器访问它们的

四、使用欺骗性代理服务器的情况:Distorting Proxies
REMOTE_ADDR = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP(经过多个代理服务器时,这个值类似:220.4.251.159, 203.98.182.163, 203.129.72.215)
这种情况下同样透露了客户端是使用了代理服务器,但编造了一个虚假的随机IP(220.4.251.159)代替客户端的真实IP来欺骗它

五、使用高匿名代理服务器的PHP获取客户端IP情况:High Anonymity Proxies (Elite proxies)
REMOTE_ADDR = 代理服务器 IP

HTTP_X_FORWARDED_FOR = 没数值或不显示

无论是REMOTE_ADDR还是HTTP_FORWARDED_FOR,这些头消息未必能够取得到,因为不同的浏览器不同的网络设备可能发送不同的IP头消息.因此PHP使用$_SERVER["REMOTE_ADDR"] 、$_SERVER["HTTP_X_FORWARDED_FOR"] 获取的值可能是空值也可能是"unknown"值

另外,IPv4转数值型:sprintf('%u', ip2long($ip)) 这样可以避免负值的出现

来源:http://www.cnblogs.com/jiji262/archive/2012/07/12/2587725.html

2024-05-21 星期二 农历四月十四