Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenjoezhang committed Jul 2, 2018
0 parents commit e65bf93
Show file tree
Hide file tree
Showing 12 changed files with 1,803 additions and 0 deletions.
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

193 changes: 193 additions & 0 deletions captcha-code.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
<?php
/**
* 安全验证码
*
* 安全的验证码要:验证码文字扭曲、旋转,使用不同字体,添加干扰码
*
* @author 流水孟春 <cmpan(at)qq.com>
* @link http://labs.yulans.cn/YL_Security_Secoder
* @link http://wiki.yulans.cn/docs/yl/security/secoder
*/
class YL_Security_Secoder {

/**
* 验证码中的参数
* @var string
*/
//验证码位数
public static $code = array('', '', '', '');

protected static $fontSize = 25; //验证码字体大小(px)
protected static $useCurve = true; //是否画混淆曲线
protected static $useNoise = true; //是否添加杂点
protected static $bg = array(243, 251, 254); //背景

protected static $fonts = array(); //'站酷酷黑', 'simhei', 'simfang', 'simkai', '本墨竞圆', '庞门正道标题体2.0增强版', '站酷快乐体2016修订版', '经典隶变简'
protected static $image_L = 0; //验证码图片长
protected static $image_H = 0; //验证码图片宽
protected static $image = null; //验证码图片实例
protected static $color = null; //验证码字体颜色

function __construct($code) {
self::$code = $code;
}

/**
* 输出验证码
* 内容为self::$code,字体和颜色随机
*/
public static function entry() {
//图片宽(px)
self::$image_L || self::$image_L = self::$fontSize * (count(self::$code) * 1.6 + 0.8);
//图片高(px)
self::$image_H || self::$image_H = self::$fontSize * 2;
//建立一幅 self::$image_L x self::$image_H 的图像
self::$image = imagecreate(self::$image_L, self::$image_H);
//设置背景
imagecolorallocate(
self::$image,
self::$bg[0],
self::$bg[1],
self::$bg[2]
);
//验证码字体随机颜色
self::$color = imagecolorallocate(
self::$image,
mt_rand(1, 120),
mt_rand(1, 120),
mt_rand(1, 120)
);

if (self::$useCurve) {
//绘干扰线
self::_writeCurve();
}
if (self::$useNoise) {
//绘杂点
self::_writeNoise();
}

//验证码使用随机字体
$all_files = scandir(dirname(__FILE__).'/fonts/');
foreach ($all_files as $fontname) {
if (preg_match('/(.*)\.ttf/', $fontname)) {
array_push(self::$fonts, $fontname);
}
}
//绘验证码
for ($i = 0; $i < count(self::$code); $i++) {
$codeNX = self::$fontSize * mt_rand(16 * $i + 4, 16 * $i + 12) / 10; //验证码第N个字符的左边距
$ttf = dirname(__FILE__).'/fonts/'.self::$fonts[mt_rand(0, count(self::$fonts) - 1)];
//写一个验证码字符
imagettftext(
self::$image,
self::$fontSize,
mt_rand(-30, 30),
$codeNX,
self::$fontSize * 1.5,
self::$color,
$ttf,
self::$code[$i]
);
}
/* Show captcha image in the page html page */
header('Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Content-Type: image/png'); //defining the image type to be shown in browser window

//输出图像
imagepng(self::$image); //showing the image
imagedestroy(self::$image); //destroying the image instance
}

/**
* 画一条由两条连在一起构成的随机正弦函数曲线作干扰线(你可以改成更帅的曲线函数)
*
* 高中的数学公式咋都忘了涅,写出来
* 正弦型函数解析式:y=Asin(ωx+φ)+b
* 各常数值对函数图像的影响:
* A:决定峰值(即纵向拉伸压缩的倍数)
* b:表示波形在Y轴的位置关系或纵向移动距离(上加下减)
* φ:决定波形与X轴位置关系或横向移动距离(左加右减)
* ω:决定周期(最小正周期T=2π/∣ω∣)
*
*/
protected static function _writeCurve() {
$A = mt_rand(1, self::$image_H / 2); //振幅
$b = mt_rand(-self::$image_H / 4, self::$image_H / 4); //Y轴方向偏移量
$f = mt_rand(-self::$image_H / 4, self::$image_H / 4); //X轴方向偏移量
$T = mt_rand(self::$image_H * 1.5, self::$image_L * 2); //周期
$w = (2* M_PI)/$T;

$px1 = 0; //曲线横坐标起始位置
$px2 = mt_rand(self::$image_L / 2, self::$image_L * 0.667); //曲线横坐标结束位置
for ($px = $px1; $px <= $px2; $px += 0.9) {
if ($w != 0) {
$py = $A * sin($w * $px + $f) + $b + self::$image_H / 2; //y = Asin(ωx+φ) + b
$i = (int) ((self::$fontSize - 6) / 4);
while ($i > 0) {
imagesetpixel(
self::$image,
$px + $i,
$py + $i,
self::$color
); //使用while循环画像素点比imagettftext和imagestring用字体大小一次画出性能要好很多
$i--;
}
}
}

$A = mt_rand(1, self::$image_H / 2); //振幅
$f = mt_rand(-self::$image_H / 4, self::$image_H / 4); //X轴方向偏移量
$T = mt_rand(self::$image_H * 1.5, self::$image_L * 2); //周期
$w = (2* M_PI)/$T;
$b = $py - $A * sin($w * $px + $f) - self::$image_H / 2;
$px1 = $px2;
$px2 = self::$image_L;
for ($px = $px1; $px <= $px2; $px += 0.9) {
if ($w != 0) {
$py = $A * sin($w * $px + $f)+ $b + self::$image_H / 2; //y = Asin(ωx+φ) + b
$i = (int) ((self::$fontSize - 8) / 4);
while ($i > 0) {
imagesetpixel(
self::$image,
$px + $i,
$py + $i,
self::$color
);
$i--;
}
}
}
}

/**
* 画杂点
* 往图片上写不同颜色的字母或数字
*/
protected static function _writeNoise() {
$noiseSet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
for ($i = 0; $i < 10; $i++) {
//杂点颜色
$noiseColor = imagecolorallocate(
self::$image,
mt_rand(150, 225),
mt_rand(150, 225),
mt_rand(150, 225)
);
for ($j = 0; $j < 5; $j++) {
//绘杂点
imagestring(
self::$image,
5,
mt_rand(-10, self::$image_L),
mt_rand(-10, self::$image_H),
$noiseSet[mt_rand(0, strlen($noiseSet) - 1)], //杂点文本为随机的字母或数字
$noiseColor
);
}
}
}
}
?>
135 changes: 135 additions & 0 deletions captcha.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php
session_start();
if (isset($_SESSION['captcha_time']) && time() - intval($_SESSION['captcha_time']) < 1) {
$protocol = $_SERVER['HTTPS'] ? 'https://' : 'http://';
header('Location: '.dirname($protocol.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']).'/default.png');
die();
}

$code_flag = true;
$characters_on_image = 6;

if (isset($_SESSION['total_no_of_characters']) && $_SESSION['total_no_of_characters']) {
$characters_on_image = $_SESSION['total_no_of_characters'];
}

//The characters that can be used in the CAPTCHA code.
//Avoid confusing characters (l 1 and i for example)
//使用的字符,01IO容易混淆,建议不用
if (isset($_SESSION['captcha_type']) && $_SESSION['captcha_type'] == 'alphanumeric') {
switch ($_SESSION['captcha_letters']) {
case 'capital':
$possible_letters = '23456789ABCDEFGHIJKLMNPQRSTUVWXYZ';
break;
case 'small':
$possible_letters = '23456789abcdefghijkmnpqrstvwxyz';
break;
case 'capitalsmall':
$possible_letters = '23456789abcdefghjkmnpqrstvwxyzABCEFGHJKMNPRSTVWXYZ';
break;
default:
$possible_letters = '23456789abcdefghjkmnpqrstvwxyz';
break;
}
}
elseif (isset($_SESSION['captcha_type']) && $_SESSION['captcha_type'] == 'alphabets') {
switch ($_SESSION['captcha_letters']) {
case 'capital':
$possible_letters = 'ABCDEFGHIJKLMNPQRSTUVWXYZ';
break;
case 'small':
$possible_letters = 'bcdfghjkmnpqrstvwxyz';
break;
case 'capitalsmall':
$possible_letters = 'bcdfghjkmnpqrstvwxyzABCEFGHJKMNPRSTVWXYZ';
break;
default:
$possible_letters = 'abcdefghijkmnpqrstuvwxyz';
break;
}
}
elseif (isset($_SESSION['captcha_type']) && $_SESSION['captcha_type'] == 'numbers') {
$possible_letters = '0123456789';
}
elseif (isset($_SESSION['captcha_type']) && $_SESSION['captcha_type'] == 'chinese') {
$possible_letters = '一乙二十丁厂七卜人入八九几儿了力乃刀又三于干亏士工土才寸下大丈与万上小口巾山千乞川亿个勺久凡及夕丸么广亡门义之尸弓己已子卫也女飞刃习叉马乡丰王井开夫天无元专云扎艺木五支厅不太犬区历尤友匹车巨牙屯比互切瓦止少日中冈贝内水见午牛手毛气升长仁什片仆化仇币仍仅斤爪反介父从今凶分乏公仓月氏勿欠风丹匀乌凤勾文六方火为斗忆订计户认心尺引丑巴孔队办以允予劝双书幻玉刊示末未击打巧正扑扒功扔去甘世古节本术汇头汉宁穴它讨写让礼训必议讯记永司尼民出汁丙左厉右石布龙平灭轧东卡北占业旧帅归且旦目叶甲申叮电号田由史只央兄叼叫另叨叹四生失禾丘付仗代仙们仪白仔他斥瓜乎丛令用甩印乐句匆册犯外处冬鸟务包饥主市立闪兰半辽奶奴加召皮边发孕圣对台矛纠母幼丝可式刑动扛寺吉扣考托老执巩圾扩扫地扬场耳共芒亚芝朽朴机权过臣再协西压厌在有百存而页匠夸夺灰达列成夹轨邪划迈毕至此贞师尘尖劣光当早吐吓虫曲团同吊吃因吸吗屿帆岁回岂刚则肉网年朱先丢舌竹迁乔伟传乒乓休伍伏优伐延件任伤价份华仰仿伙伪自血向似后行舟全会杀合兆企众爷伞创肌朵杂危旬旨负各名多争色壮冲冰庄庆亦刘齐交次衣产决充妄闭问闯羊并关米灯州汗污江池汤忙兴宇守宅字安讲军许论农讽设访寻那迅尽导异孙阵阳收阶阴防奸如妇好她妈戏羽观欢买红纤级约纪驰巡寿弄麦形进戒吞远违运扶抚坛技坏扰拒找批扯址走抄坝贡攻赤折抓扮抢孝均抛投坟抗坑坊抖护壳志扭块声把报却劫芽花芹芬苍芳严芦劳克苏杆杠杜材村杏极李杨求更束豆两丽医辰励否还歼来连步坚旱盯呈时吴助县里呆园旷围呀吨足邮男困吵串员听吩吹呜吧吼别岗帐财针钉告我乱利秃秀私每兵估体何但伸作伯伶佣低你住位伴身皂佛近彻役返余希坐谷妥含邻岔肝肚肠龟免狂犹角删条卵岛迎饭饮系言冻状亩况床库疗应冷这序辛弃冶忘闲间闷判灶灿弟汪沙汽沃泛沟没沈沉怀忧快完宋宏牢究穷灾良证启评补初社识诉诊词译君灵即层尿尾迟局改张忌际陆阿陈阻附妙妖妨努忍劲鸡驱纯纱纳纲驳纵纷纸纹纺驴纽奉玩环武青责现表规抹拢拔拣担坦押抽拐拖拍者顶拆拥抵拘势抱垃拉拦拌幸招坡披拨择抬其取苦若茂苹苗英范直茄茎茅林枝杯柜析板松枪构杰述枕丧或画卧事刺枣雨卖矿码厕奔奇奋态欧垄妻轰顷转斩轮软到非叔肯齿些虎虏肾贤尚旺具果味昆国昌畅明易昂典固忠咐呼鸣咏呢岸岩帖罗帜岭凯败贩购图钓制知垂牧物乖刮秆和季委佳侍供使例版侄侦侧凭侨佩货依的迫质欣征往爬彼径所舍金命斧爸采受乳贪念贫肤肺肢肿胀朋股肥服胁周昏鱼兔狐忽狗备饰饱饲变京享店夜庙府底剂郊废净盲放刻育闸闹郑券卷单炒炊炕炎炉沫浅法泄河沾泪油泊沿泡注泻泳泥沸波泼泽治怖性怕怜怪学宝宗定宜审宙官空帘实试郎诗肩房诚衬衫视话诞询该详建肃录隶居届刷屈弦承孟孤陕降限妹姑姐姓始驾参艰线练组细驶织终驻驼绍经贯奏春帮珍玻毒型挂封持项垮挎城挠政赴赵挡挺括拴拾挑指垫挣挤拼挖按挥挪某甚革荐巷带草茧茶荒茫荡荣故胡南药标枯柄栋相查柏柳柱柿栏树要咸威歪研砖厘厚砌砍面耐耍牵残殃轻鸦皆背战点临览竖省削尝是盼眨哄显哑冒映星昨畏趴胃贵界虹虾蚁思蚂虽品咽骂哗咱响哈咬咳哪炭峡罚贱贴骨钞钟钢钥钩卸缸拜看矩怎牲选适秒香种秋科重复竿段便俩贷顺修保促侮俭俗俘信皇泉鬼侵追俊盾待律很须叙剑逃食盆胆胜胞胖脉勉狭狮独狡狱狠贸怨急饶蚀饺饼弯将奖哀亭亮度迹庭疮疯疫疤姿亲音帝施闻阀阁差养美姜叛送类迷前首逆总炼炸炮烂剃洁洪洒浇浊洞测洗活派洽染济洋洲浑浓津恒恢恰恼恨举觉宣室宫宪突穿窃客冠语扁袄祖神祝误诱说诵垦退既屋昼费陡眉孩除险院娃姥姨姻娇怒架贺盈勇怠柔垒绑绒结绕骄绘给络骆绝绞统耕耗艳泰珠班素蚕顽盏匪捞栽捕振载赶起盐捎捏埋捉捆捐损都哲逝捡换挽热恐壶挨耻耽恭莲莫荷获晋恶真框桂档桐株桥桃格校核样根索哥速逗栗配翅辱唇夏础破原套逐烈殊顾轿较顿毙致柴桌虑监紧党晒眠晓鸭晃晌晕蚊哨哭恩唤啊唉罢峰圆贼贿钱钳钻铁铃铅缺氧特牺造乘敌秤租积秧秩称秘透笔笑笋债借值倚倾倒倘俱倡候俯倍倦健臭射躬息徒徐舰舱般航途拿爹爱颂翁脆脂胸胳脏胶脑狸狼逢留皱饿恋桨浆衰高席准座脊症病疾疼疲效离唐资凉站剖竞部旁旅畜阅羞瓶拳粉料益兼烤烘烦烧烛烟递涛浙涝酒涉消浩海涂浴浮流润浪浸涨烫涌悟悄悔悦害宽家宵宴宾窄容宰案请朗诸读扇袜袖袍被祥课谁调冤谅谈谊剥恳展剧屑弱陵陶陷陪娱娘通能难预桑绢绣验继球理捧堵描域掩捷排掉堆推掀授教掏掠培接控探据掘职基著勒黄萌萝菌菜萄菊萍菠营械梦梢梅检梳梯桶救副票戚爽聋袭盛雪辅辆虚雀堂常匙晨睁眯眼悬野啦晚啄距跃略蛇累唱患唯崖崭崇圈铜铲银甜梨犁移笨笼笛符第敏做袋悠偿偶偷您售停偏假得衔盘船斜盒鸽悉欲彩领脚脖脸脱象够猜猪猎猫猛馅馆凑减毫麻痒痕廊康庸鹿盗章竟商族旋望率着盖粘粗粒断剪兽清添淋淹渠渐混渔淘液淡深婆梁渗情惜惭悼惧惕惊惨惯寇寄宿窑密谋谎祸谜逮敢屠弹随蛋隆隐婚婶颈绩绪续骑绳维绵绸绿琴斑替款堪搭塔越趁趋超提堤博揭喜插揪搜煮援裁搁搂搅握揉斯期欺联散惹葛董葡敬葱落朝辜葵棒棋植森椅椒棵棍棉棚棕惠惑逼厨厦硬确雁殖裂雄暂雅辈悲紫辉敞赏掌晴暑最量喷晶喇遇喊景践跌跑遗蛙蛛蜓蛤喝喂喘喉幅帽赌赔黑铸铺链销锁锄锅锈锋锐短智毯鹅剩稍程稀税筐等筑策筛筒答筋筝傲傅牌堡集焦傍储奥街惩御循艇舒番释禽腊脾腔鲁猾猴然馋装蛮就痛童阔善羡普尊道曾焰港湖渣湿温渴滑湾渡游滋溉愤慌惰愧愉慨割寒富窜窝窗遍裕裤裙谢谣谦属屡强粥疏隔隙絮嫂登缎缓编骗缘瑞魂肆摄摸填搏塌鼓摆携搬摇搞塘摊蒜勤鹊蓝墓幕蓬蓄蒙蒸献禁楚想槐榆楼概赖酬感碍碑碎碰碗碌雷零雾雹输督龄鉴睛睡睬鄙愚暖盟歇暗照跨跳跪路跟遣蛾蜂嗓置罪罩错锡锣锤锦键锯矮辞稠愁筹签简毁舅鼠催傻像躲微愈遥腰腥腹腾腿触解酱痰廉新韵意粮数煎塑慈煤煌满漠源滤滥滔溪溜滚滨粱滩慎誉塞谨福群殿辟障嫌嫁叠缝缠静碧璃墙撇嘉摧截誓境摘摔聚蔽慕暮蔑模榴榜榨歌遭酷酿酸磁愿需弊裳颗嗽蜻蜡蝇蜘赚锹锻舞稳算箩管僚鼻魄貌膜膊膀鲜疑馒裹敲豪膏遮腐瘦辣竭端旗精歉熄熔漆漂漫滴演漏慢寨赛察蜜谱嫩翠熊凳骡缩慧撕撒趣趟撑播撞撤增聪鞋蕉蔬横槽樱橡飘醋醉震霉瞒题暴瞎影踢踏踩踪蝶蝴嘱墨镇靠稻黎稿稼箱箭篇僵躺僻德艘膝膛熟摩颜毅糊遵潜潮懂额慰劈操燕薯薪薄颠橘整融醒餐嘴蹄器赠默镜赞篮邀衡膨雕磨凝辨辩糖糕燃澡激懒壁避缴戴擦鞠藏霜霞瞧蹈螺穗繁辫赢糟糠燥臂翼骤鞭覆蹦镰翻鹰警攀蹲颤瓣爆疆壤耀躁嚼嚷籍魔灌蠢霸露囊罐'; //Unicode Chinese Characters
}
elseif (isset($_SESSION['captcha_type']) && $_SESSION['captcha_type'] == 'math') {
$code_flag = false;
}
else {
$possible_letters = '0123456789';
}

if ($code_flag) {
$code = array(); //Captcha code
for ($i = 0; $i < $characters_on_image; $i++) {
$code[$i] = mb_substr($possible_letters, mt_rand(0, mb_strlen($possible_letters) - 1), 1);
}
$_SESSION['captcha_code'] = join('', $code); //Save to SESSION
}
else {
$operator = mt_rand(0, 2);
$position = mt_rand(0, 2);
if ($operator == 0) {
$a = mt_rand(1, 99);
$b = mt_rand(1, 99);
$c = $a + $b;
if ($position == 0) {
$answer = $a;
$code = sprintf("?+%d=%d", $b, $c);
}
elseif ($position == 1) {
$answer = $b;
$code = sprintf("%d+?=%d", $a, $c);
}
elseif ($position == 2) {
$answer = $c;
$code = sprintf("%d+%d=?", $a, $b);
}
}
elseif ($operator == 1) {
$a = mt_rand(1, 99);
$b = mt_rand(1, 99);
$c = $a - $b;
if ($position == 0) {
$answer = $a;
$code = sprintf("?-%d=%d", $b, $c);
}
elseif ($position == 1) {
$answer = $b;
$code = sprintf("%d-?=%d", $a, $c);
}
elseif ($position == 2) {
$answer = $c;
$code = sprintf("%d-%d=?", $a, $b);
}
}
elseif ($operator == 2) {
$a = mt_rand(1, 10);
$b = mt_rand(1, 10);
$c = $a * $b;
if ($position == 0) {
$answer = $a;
$code = sprintf("?*%d=%d", $b, $c);
}
elseif ($position == 1) {
$answer = $b;
$code = sprintf("%d*?=%d", $a, $c);
}
elseif ($position == 2) {
$answer = $c;
$code = sprintf("%d*%d=?", $a, $b);
}
}
$code = str_split($code);
$_SESSION['captcha_code'] = $answer;
}

require_once 'captcha-code.php';
$captcha = new YL_Security_Secoder($code);
$captcha->entry();

$_SESSION['captcha_time'] = time(); //验证码创建时间 unix timestamp (s)

?>
Binary file added default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit e65bf93

Please sign in to comment.