关于php in_array函数使用的问题
先介绍一下需求背景:
发票方式:
0=捐赠(不要问我为什么,历史原因)
1=对中寄送
2=索取
3=电子发票
现在要对用户提交的数据进行检测:
if(!in_array($_POST['invoice_action'], array(0,1,2,3))){
throw new Exception('请选择正确的发票方式');
}
这个时候出现一个问题,如果压根就不存在$_POST[‘invoice_action’]这个值,为什么没有抛出异常?
经确认,这就是PHP作为弱类型语言的一个坑!!!没错,这是一个坑!!!
看一下这组代码:
echo in_array('', array(0)) ? 1 : 0; // 结果:1
echo in_array(null, array(0)) ? 1 : 0; // 结果:1
echo in_array(false, array(0)) ? 1 : 0; // 结果:1
这么大一个坑,我们要怎么绕过或者填起呢?
方法一:in_array支持第三个参数,强制对数据类型检测
echo in_array('', array(0), true) ? 1 : 0; // 结果:0
echo in_array(null, array(0), true) ? 1 : 0; // 结果:0
echo in_array(false, array(0), true) ? 1 : 0; // 结果:0
方法二:依然是数据类型方向,把数组中的0改为字符串
echo in_array('', array('0'), true) ? 1 : 0; // 结果:0
echo in_array(null, array('0'), true) ? 1 : 0; // 结果:0
echo in_array(false, array('0'), true) ? 1 : 0; // 结果:0
这段时间在写php脚本,接触到web前端以及web安全问题比较多,这时给大家简单地谈一下我们网站验证码的验证过程及其安全问题。
从三个方面去谈一下关于验证码的使用:验证码的生成,验证的过程,验证中注意的安全问题。
验证码的生成,首先还是要说说验证码的作用。众所周知,验证码的存在,是为了防止一些机器,或是刷恶意留言、无限注册用户或是暴力破解账号密码。现在普通的验证码是由一个php脚本生成的,比如打开我们emlog的include/lib/文件夹,底下有个checkcode.php,这就是生成验证码的脚本。
我们可以简单看一下它的代码:
session_start();
$randCode = '';
$chars = 'abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPRSTUVWXYZ23456789';
for ( $i = 0; $i < 5; $i++ ){
$randCode .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
$_SESSION['code'] = strtoupper($randCode);
$img = imagecreate(70,22);
$bgColor = isset($_GET['mode']) && $_GET['mode'] == 't' ? imagecolorallocate($img,245,245,245) : imagecolorallocate($img,255,255,255);
$pixColor = imagecolorallocate($img,mt_rand(30, 180), mt_rand(10, 100), mt_rand(40, 250));
for($i = 0; $i < 5; $i++){
$x = $i * 13 + mt_rand(0, 4) - 2;
$y = mt_rand(0, 3);
$text_color = imagecolorallocate($img, mt_rand(30, 180), mt_rand(10, 100), mt_rand(40, 250));
imagechar($img, 5, $x + 5, $y + 3, $randCode[$i], $text_color);
}
for($j = 0; $j < 60; $j++){
$x = mt_rand(0,70);
$y = mt_rand(0,22);
imagesetpixel($img,$x,$y,$pixColor);
}
header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);
第一个for循环在$chars这个字符串中随机取了5个字符,这实际上就是我们的真实验证码。然后我们可以看到:$_SESSION['code'] = strtoupper($randCode); 他把我们的验证码转换成大写赋值到session里了。
有的朋友要问,问什么赋值到SESSION里了不赋值到COOKIE里。这就说明你对他们二者关系不了解。cookie和session都作为网站临时保存客户端相关信息的一个“容器”,但是cookie是保存在客户端里的,也就是网站的访问者可以随意查看和修改cookie里的内容,那就没有验证码存在的意义了,因为用户可以直接从cookie中读到验证码,当然机器也可以。而session是保存在服务器上的内容,我生成好的验证码,用户不可能读取到。
再看源码,后面的两个循环分别是生成彩色的带验证码的图片和在图片上加噪点。是为了加大机器识别验证码的难度。最后我们看到,header('Content-Type: image/png'); 把我们这个页面定义成为图片的格式。
这样,我们就可以用html代码来让验证码显示出来:
<img src="checkcode.php" />
类似这样:
那么验证的过程就是,我们首先生成5个随机字符,保存到session里。然后把这5个字符画成一个图片给用户看,让用户识别,填写在表单里提交后和我们session里的验证码比对。
其实就是这么简单。
最后来说说验证码的安全性。我们emlog和wordpress其实验证码并不是很强大,我们这个简单的验证码可以写一个小脚本很容易地识别,所以并不适合比较大型的网站使用。像类似腾讯、百度这种网站的验证码很多字符能旋转、扭曲,并且背影上的干扰物更多,甚至是中文验证码。不过对于小型网站来说,普通等级的验证码足矣防范很多刷评论的机器。
还有一点很重要,注意验证码使用过后要记住删除相应的session。否则验证码就失去了其意义,这也是我之前犯过的错误。
为什么这么说。作为一个正常用户,我们每访问一次需要填写验证码的页面,生成验证码的脚本都会执行一次,也就说会生成一个新验证码赋值到session里,没有任何问题。但对于一个机器(或一个暴力破解密码脚本),它第一次访问需要填写验证码的页面,然后在session中得到一个验证码,它以后就不用再次访问这个页面了。直接把第一次的数据包更改并再次发送即可,于是,如果没有清除session的网站,每次的验证码都和第一次相同,也就丧失了验证码的本来作用。
这是我们做网站需要注意的地方。希望大家在写程序的时候多注意网站的安全性,避免在网站发布后出现问题
通过网上的一些实例,拼凑出一个验证码登陆测试程序。详细代码如下:
生成验证码程序ttt.php。通过random生成随机数,然后保存在session里:
login.htm页面
<html>
<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head>
<title>login</title>
<style type="text/css">
<!--
.textbox {
height: 18px;
width: 100px;
}
.text {
font-size: 14px;
vertical-align: bottom;
color: #0000FF;
}
.style1 {
font-size: 18px;
color: #0000FF;
font-family: "幼圆";
}
-->
</style>
</head>
<body>
<table width="200">
<tr><td align="center" valign="bottom" class="style1" bgcolor="#C7D3F9">请输入验证码</td>
</tr>
</table>
<form method="post" action="login.php">
<table width="200" border="0" bgcolor="C7D3F9">
<tr>
<td class="text">验证码:</td>
<td align="right" valign="bottom"><input type="text" name="auth" class="textbox"></td>
</tr>
</table>
<img src="ttt.php?act=yes" align="middle">
<table width="200"><tr><td align="right"><input type="button" value="看不清楚验证码" onclick="window.location.reload();"><input name="submit" type="submit" value="Submit"></td></tr></table>
</form>
</body>
</html>
login.php
<?php
session_start();
$name = $_POST['user'];
$password = $_POST['passwd'];
$auth = $_POST['auth'];
#require("db.php");
#$db = new db();
#$sql = "select * from user where name = '$name' and password = '$password'";
#$result = $db->query($sql);
if($_SESSION['seccode'] == $auth)
{
#$_SESSION['user'] = $name;
#$_SESSION['passwd'] = $password;
# header("Location: main.php");
#echo ("登录成功!");
$_SESSION['seccode']='';
print '
<script language=javascript>
alert("登录成功!");
</script>';
}else
{
print '
<script language=javascript>
alert("登录失败,请重新登录!");
self.window.location="login.html";
</script>';
}
?>
ttt.php验证码生成程序
<?php
session_start();
function random($length, $numeric = 0) {
mt_srand((double)microtime() * 1000000);
if($numeric) {
$hash = sprintf('%0'.$length.'d', mt_rand(0, pow(10, $length) - 1));
} else {
$hash = '';
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
$max = strlen($chars) - 1;
for($i = 0; $i < $length; $i++) {
$hash .= $chars[mt_rand(0, $max)];
}
}
return $hash;
}
#if(preg_replace("/https?:\/\/([^\:\/]+).*/i", "\\1", $_SERVER['HTTP_REFERER']) != preg_replace("/([^\:]+).*/", "\\1", $_SERVER['HTTP_HOST'])) {
# exit('Access Denied');
#}
//if($_GET['update']) {
$seccode = random(4, 1);
//}
#if($seccode < 1 || $seccode > 9999) {
# exit('Access Denied');
#}
$_SESSION['seccode'] = $seccode;
$seccode = sprintf('%04d', $seccode);
if(!$nocacheheaders) {
@header("Expires: -1");
@header("Cache-Control: no-store, private, post-check=0, pre-check=0, max-age=0", FALSE);
@header("Pragma: no-cache");
}
if(function_exists('imagecreate') && function_exists('imagecolorset') && function_exists('imagecopyresized') && function_exists('imagecolorallocate') && function_exists('imagesetpixel') && function_exists('imagechar') && function_exists('imagecreatefromgif') && function_exists('imagepng')) {
$im = imagecreate(62, 25);
$backgroundcolor = imagecolorallocate ($im, 255, 255, 255);
$numorder = array(1, 2, 3, 4);
shuffle($numorder);
$numorder = array_flip($numorder);
for($i = 1; $i <= 4; $i++) {
$imcodefile = 'seccode/'.$seccode[$numorder[$i]].'.gif';
$x = $numorder[$i] * 13 + mt_rand(0, 4) - 2;
$y = mt_rand(0, 3);
if(file_exists($imcodefile)) {
$imcode = imagecreatefromgif($imcodefile);
$data = getimagesize($imcodefile);
imagecolorset($imcode, 0 ,mt_rand(50, 255), mt_rand(50, 128), mt_rand(50, 255));
imagecopyresized($im, $imcode, $x, $y, 0, 0, $data[0] + mt_rand(0, 6) - 3, $data[1] + mt_rand(0, 6) - 3, $data[0], $data[1]);
} else {
$text_color = imagecolorallocate($im, mt_rand(50, 255), mt_rand(50, 128), mt_rand(50, 255));
imagechar($im, 5, $x + 5, $y + 3, $seccode[$numorder[$i]], $text_color);
}
}
$linenums = mt_rand(10, 32);
for($i=0; $i <= $linenums; $i++) {
$linecolor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
$linex = mt_rand(0, 62);
$liney = mt_rand(0, 25);
imageline($im, $linex, $liney, $linex + mt_rand(0, 4) - 2, $liney + mt_rand(0, 4) - 2, $linecolor);
}
for($i=0; $i <= 64; $i++) {
$pointcolor = imagecolorallocate($im, mt_rand(50, 255), mt_rand(50, 255), mt_rand(50, 255));
imagesetpixel($im, mt_rand(0, 62), mt_rand(0, 25), $pointcolor);
}
$bordercolor = imagecolorallocate($im , 150, 150, 150);
imagerectangle($im, 0, 0, 61, 24, $bordercolor);
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
} else {
$numbers = array
(
0 => array('3c','66','66','66','66','66','66','66','66','3c'),
1 => array('1c','0c','0c','0c','0c','0c','0c','0c','1c','0c'),
2 => array('7e','60','60','30','18','0c','06','06','66','3c'),
3 => array('3c','66','06','06','06','1c','06','06','66','3c'),
4 => array('1e','0c','7e','4c','2c','2c','1c','1c','0c','0c'),
5 => array('3c','66','06','06','06','7c','60','60','60','7e'),
6 => array('3c','66','66','66','66','7c','60','60','30','1c'),
7 => array('30','30','18','18','0c','0c','06','06','66','7e'),
8 => array('3c','66','66','66','66','3c','66','66','66','3c'),
9 => array('38','0c','06','06','3e','66','66','66','66','3c')
);
for($i = 0; $i < 10; $i++) {
for($j = 0; $j < 6; $j++) {
$a1 = substr('012', mt_rand(0, 2), 1).substr('012345', mt_rand(0, 5), 1);
$a2 = substr('012345', mt_rand(0, 5), 1).substr('0123', mt_rand(0, 3), 1);
mt_rand(0, 1) == 1 ? array_push($numbers[$i], $a1) : array_unshift($numbers[$i], $a1);
mt_rand(0, 1) == 0 ? array_push($numbers[$i], $a1) : array_unshift($numbers[$i], $a2);
}
}
$bitmap = array();
for($i = 0; $i < 20; $i++) {
for($j = 0; $j < 4; $j++) {
$n = substr($seccode, $j, 1);
$bytes = $numbers[$n][$i];
$a = mt_rand(0, 14);
switch($a) {
case 1: str_replace('9', '8', $bytes); break;
case 3: str_replace('c', 'e', $bytes); break;
case 6: str_replace('3', 'b', $bytes); break;
case 8: str_replace('8', '9', $bytes); break;
case 0: str_replace('e', 'f', $bytes); break;
}
array_push($bitmap, $bytes);
}
}
for($i = 0; $i < 8; $i++) {
$a = substr('012', mt_rand(0, 2), 1) . substr('012345', mt_rand(0, 5), 1);
array_unshift($bitmap, $a);
array_push($bitmap, $a);
}
$image = pack('H*', '424d9e000000000000003e000000280000002000000018000000010001000000'.
'0000600000000000000000000000000000000000000000000000FFFFFF00'.implode('', $bitmap));
header('Content-Type: image/bmp');
echo $image;
}
?>
php的慢速日志引起的Mysql 2013错误怎么办,下面我们就一起来看看这个问题的解决办法,希望例子能够帮助到各位。
Description:
————
If mysql query is longer as request_slowlog_timeout, connection breaks.
Test script:
<?php
// request_slowlog_timeout = 10s (at /etc/php5/fpm/php-fpm.conf)
// $mysqli =
// ...
$query = "SELECT SLEEP (15)";
$res = $mysqli->query($query);
if (!$res) {
echo $mysqli->error; // Error Code: 2013. Lost connection to MySQL server during query
exit;
}
Expected result:
—————-
connection must be preserved and the request should be executed
php 网页采集程序总结,最近帮朋友做了个采集程序
以www.xxxx.com/shop_list.php?page=1&province=%B1%B1%BE%A9为例
%B1%B1%BE%A9是gb2312的转码,例如
$aa=”北京”;
$aa = @iconv(“utf-8″, “gb2312″,$aa);
echo $bb=urlencode($aa);
我们通过file_get_contents($url) 抓取网页 当然也可以是curl
function getHtml($url){
$ch2 = curl_init($url);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1);
$html = curl_exec($ch2);
curl_close($ch2);
return $html;
}
抓取我们想要的页面数据,可以设定从哪个位置到哪个位置的区间,取出中间数据,通过以下方法实现
function findneed($wholestr,$strkey1,$strkey2)
{
$num1 = strpos($wholestr , $strkey1)+strlen($strkey1);
$num2 = strpos($wholestr ,$strkey2);
$needstr =substr($wholestr ,$num1,$num2-$num1 );
return $needstr;
}
当然这是一种方法,我们只要写出一个php即可,根据分页抓取,但是如果都放在循环里面,岂不是很慢
我们介绍另个算法
<script>
location.href=”index.php?page=<?=$page?>&provinceIndex=<?=$provinceIndex?>&totalPage=<?=$totalPage?>”;
</script>
通过实现网页跳转页数,抓取,访问程序,不断跳转页数,把当前url的page 数组保存到数据库
其他的无非是些正则表达式的用法:
比如我们想取页面中的所有城市
可用preg_match_all(‘/<select name=”province”(.*?)>(.*?)<\/select>/s’,$html,$selects);即可
(.*?)表示任意字符 . 是任何东西 * 是0至无限 ? 是0至1
还有种算法是递归,类似循环取值
function collectionProvinceData($url,$province,$page=1,$totalPage=-1){
if($page>$totalPage&&$totalPage>-1){
return false;
}
$collectionUrl = $url."?page=".$page."&province=".urlencode(iconv('UTF-8', 'GB2312', $province));
echo "当前url:".$province."第{$page}页 url".$collectionUrl."<hr/>";
$html = getHtml($collectionUrl);
$html = mb_convert_encoding($html, 'UTF-8', 'UTF-8,GBK,GB2312,BIG5');
if($totalPage==-1){
$latestPageNum = getLatestPageNum($html);
if($latestPageNum>0){
$totalPage = $latestPageNum;
}
}
$dataRows = getDataRows($html);
saveDataRowsOrNot($dataRows);
if(!empty($dataRows)){
$page++;
}
ob_flush();
flush();
collectionProvinceData($url,$province,$page,$totalPage);
}
我们要使用gd库就必须先打开gd库,具体如下
Windows下开启PHP的GD库支持
找到php.ini,打开内容,找到:
;extension=php_gd2.dll
把最前面的分号“;”去掉,再保存即可,如果本来就没有分号,那就是已经开启了。
具体可以参考下文:http://www.111cn.net/phper/php/48352.htm
一:添加文字水印 使用方法
require 'image.class.php'
$src="001.jpg";
$content="hello";
$font_url="my.ttf";
$size=20;
$image=new Image($src);
$color=array(
0=>255,
1=>255,
2=>255,
2=>20
);
$local=array(
'x'=>20,
'y'=>30
);
$angle=10;
$image->fontMark($content,$font_url,$size,$color,$local,$angle);
$image->show();
二:图片缩略图 使用方法:
require 'image.class.php'
$src="001.jpg";
$image=new Image($src);
$image->thumb(300,200);
$image->show();
三:image.class.php
class image{
private $info;
private $image;
public function __contruct($src){
$info= getimagesize($src);
$this->info=array(
'width'=> $info[0],
'height'=>$info[1],
'type'=>image_type_to_extension($info[2],false),
'mime'=>$info['mime'],
);
$fun="imagecreatefrom{$this->info['type']}";
$this->image= $fun($src);
}
//缩略图
public function thumd($width,$height){
$image_thumb= imagecreatetruecolor($width,$height);
imagecopyresampled($image_thumb,$this->image,0,0,0,0,$width,$height,$this->info['width'],$this->info['height']);
imagedestroy($this->image);
$this->image=$image_thumb;
}
//文字水印
public function fontMark($content,$font_url,$size,$color,$local,$angle){
$col=imagecolorallocatealpha($this->image,$color[0],$color[1],$color[2],$color[3]);
$text=imagettftext($this->image,$size,$angle,$local['x'],$local['y'],$col,$font_url,$content);
}
//输出图片
public function show()
{
header("Content-type:",$this->info['mime']);
$func="image{$this->info['type']}";
$func($this->image);
}
public function save($nwename){
$func="image{$this->info['type']}";
//从内存中取出图片显示
$func($this->image);
//保存图片
$func($this->image,$nwename.$this->info['type']);
}
public function _destruct(){
imagedestroy($this->image);
}
}
相关文章
- eval函数在php中是一个函数并不是系统组件函数,我们在php.ini中的disable_functions是无法禁止它的,因这他不是一个php_function哦。 eval()针对php安全来说具有很...2016-11-25
- 在php中eval是一个函数并且不能直接禁用了,但eval函数又相当的危险了经常会出现一些问题了,今天我们就一起来看看eval函数对数组的操作 例子, <?php $data="array...2016-11-25
Python astype(np.float)函数使用方法解析
这篇文章主要介绍了Python astype(np.float)函数使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-08- 有时为了网站安全和版权问题,会对自己写的php源码进行加密,在php加密技术上最常用的是zend公司的zend guard 加密软件,现在我们来图文讲解一下。 下面就简单说说如何...2016-11-25
- 这篇文章主要介绍了Python中的imread()函数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-16
- 本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
- 下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- ps软件是现在很多人都会使用到的,HSL面板在ps软件中又有着非常独特的作用。这次文章就给大家介绍下ps怎么使用HSL面板,还不知道使用方法的下面一起来看看。  ...2017-07-06
- 许多的朋友对于Plesk控制面板应用不是非常的了解特别是英文版的Plesk控制面板,在这里小编整理了一些关于Plesk控制面板常用的使用方案整理,具体如下。 本文基于Linu...2016-10-10
- CREATE FUNCTION ChangeBigSmall (@ChangeMoney money) RETURNS VarChar(100) AS BEGIN Declare @String1 char(20) Declare @String2 char...2016-11-25
使用insertAfter()方法在现有元素后添加一个新元素
复制代码 代码如下: //在现有元素后添加一个新元素 function insertAfter(newElement, targetElement){ var parent = targetElement.parentNode; if (parent.lastChild == targetElement){ parent.appendChild(newEl...2014-05-31PHP传值到不同页面的三种常见方式及php和html之间传值问题
在项目开发中经常见到不同页面之间传值在web工作中,本篇文章给大家列出了三种常见的方式。接触PHP也有几个月了,本文总结一下这段日子中,在编程过程里常用的3种不同页面传值方法,希望可以给大家参考。有什么意见也希望大...2015-11-24- 这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
- js修改input的type属性有些限制。当input元素还未插入文档流之前,是可以修改它的值的,在ie和ff下都没问题。但如果input已经存在于页面,其type属性在ie下就成了只读属性了,不可以修改。...2013-10-19
Android开发中findViewById()函数用法与简化
findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20- 1,utf8_bin跟utf8_general_ci的区别 ci是 case insensitive, 即 "大小写不敏感", a 和 A 会在字符判断中会被当做一样的; bin 是二进制, a 和 A 会别区别对待. 例如你运行: SELECT * FROM table WHERE txt = 'a'...2013-10-04
jQuery 1.9使用$.support替代$.browser的使用方法
jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support 。 在更新的 2.0 版本中,将不再支持 IE 6/7/8。 以后,如果用户需要支持 IE 6/7/8,只能使用 jQuery 1.9。 如果要全面支持 IE,并混合...2014-05-31- 大概有如下步骤 新建项目Bejs 新建文件package.json 新建文件Gruntfile.js 命令行执行grunt任务 一、新建项目Bejs源码放在src下,该目录有两个js文件,selector.js和ajax.js。编译后代码放在dest,这个grunt会...2014-06-07
使用percona-toolkit操作MySQL的实用命令小结
1.pt-archiver 功能介绍: 将mysql数据库中表的记录归档到另外一个表或者文件 用法介绍: pt-archiver [OPTION...] --source DSN --where WHERE 这个工具只是归档旧的数据,不会对线上数据的OLTP查询造成太大影响,你可以将...2015-11-24如何使用php脚本给html中引用的js和css路径打上版本号
在搜索引擎中搜索关键字.htaccess 缓存,你可以搜索到很多关于设置网站文件缓存的教程,通过设置可以将css、js等不太经常更新的文件缓存在浏览器端,这样访客每次访问你的网站的时候,浏览器就可以从浏览器的缓存中获取css、...2015-11-24