PHP 实现“贴吧神兽”验证码
最早看到 “贴吧神兽” 验证码是在百度贴吧,吧主防止挖坟贴,放出了究极神兽验证码
例如:
地址:http://tieba.baidu.com/p/3320323440
可以用 PHP + JavaScript 实现该种类型的验证码。
使用 jQuery 版本:jQuery 1.9.1
框架使用 ThinkPHP 3.2.3,自定义的验证码类基于 TP 的验证码类
最终效果图:
自定义验证码类路径:/Application/Home/Common/VerivyPostBar.class.php
控制器:/Application/Home/Controller/PostBarController.class.php
视图:/Applicable/Home/View/PostBarVerify/index.html
自定义验证码类 /Application/Home/Common/VerivyPostBar.class.php
<?php namespace Home\Common;
use Think\Verify; class VerifyPostBar extends Verify { private $_image = NULL; // 验证码图片实例
private $_color = NULL; // 验证码字体颜色 public function entryProcess($id = '') {
// 图片宽(px)
$this->imageW || $this->imageW = $this->length*$this->fontSize*1.5 + $this->length*$this->fontSize/2;
// 图片高(px)
$this->imageH || $this->imageH = $this->fontSize * 2.5; // 建立一幅 $this->imageW x $this->imageH 的透明图像
$this->_image = imagecreatetruecolor($this->imageW, $this->imageH);
imagesavealpha($this->_image, true);
$trans_colour = imagecolorallocatealpha($this->_image, 0, 0, 0, 127);
imagefill($this->_image, 0, 0, $trans_colour); // 验证码字体随机颜色
$this->_color = imagecolorallocate($this->_image, mt_rand(1,150), mt_rand(1,150), mt_rand(1,150));
// 验证码使用随机字体
$ttfPath = $_SERVER['DOCUMENT_ROOT'].'/ThinkPHP/Library/Think/Verify/' . ($this->useZh ? 'zhttfs' : 'ttfs') . '/'; if(empty($this->fontttf)){
$dir = dir($ttfPath);
$ttfs = array();
while (false !== ($file = $dir->read())) {
if($file[0] != '.' && substr($file, -4) == '.ttf') {
$ttfs[] = $file;
}
}
$dir->close();
$this->fontttf = $ttfs[array_rand($ttfs)];
}
$this->fontttf = $ttfPath . $this->fontttf; if($this->useImgBg) {
$this->_background();
} if ($this->useNoise) {
// 绘杂点
// $this->_writeNoise();
}
if ($this->useCurve) {
// 绘干扰线
$this->_writeCurve();
} // 绘验证码
$code = array(); // 验证码
$codeNX = 0; // 验证码第N个字符的左边距 if($this->useZh){ // 中文验证码
for ($i = 0; $i<$this->length; $i++) {
$code[$i] = iconv_substr($this->zhSet, $i, 1, 'utf-8');
imagettftext($this->_image, $this->fontSize, mt_rand(-40, 40), $this->fontSize*($i+1)*1.5, $this->fontSize + mt_rand(10, 20), $this->_color, $this->fontttf, $code[$i]);
} // 备选验证码区域(9个汉字)
$len_pre_row = $this->area_length / $this->rows; // 每行的字数
for($r = 0; $r < $this->rows; $r++) {
$flag = 1;
$start = $r * $len_pre_row;
$end = $r * $len_pre_row + $len_pre_row - 1;
$code_ = array();
for ($i = $start; $i<$end + 1; $i++) {
$code_[$i] = iconv_substr($this->code_area, $i, 1, 'utf-8');
// @param image
// @param size
// @param angle
// @param x
// @param y
// @param color
// @param fontfile
imagettftext($this->_image, $this->fontSize, mt_rand(-20, 20), $this->fontSize*2 * $flag, $this->fontSize + 50 * $r + 120, $this->_color, $this->fontttf, $code_[$i]);
$flag += 2; // 控制验证码备选字符的x坐标
}
}
} // 保存验证码
$key = $this->authcode($this->seKey);
$code = $this->authcode(strtoupper(implode('', $code)));
$secode = array();
$secode['verify_code'] = $code; // 把校验码保存到session
$secode['verify_time'] = NOW_TIME; // 验证码创建时间
session($key.$id, $secode); 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"); // 保存图像至硬盘
imagepng($this->_image, 'Public/Home/Images/verifyimage.png');
// 输出图像
// imagepng($this->_image);
readfile('Public/Home/Images/verifyimage.png');
imagedestroy($this->_image);
} /**
* 画杂点
* 往图片上写不同颜色的字母或数字
*/
private function _writeNoise() {
$codeSet = '2345678abcdefhijkmnpqrstuvwxyz';
for($i = 0; $i < 10; $i++){
//杂点颜色
$noiseColor = imagecolorallocate($this->_image, mt_rand(150,225), mt_rand(150,225), mt_rand(150,225));
for($j = 0; $j < 5; $j++) {
// 绘杂点
imagestring($this->_image, 5, mt_rand(-10, $this->imageW), mt_rand(-10, $this->imageH), $codeSet[mt_rand(0, 29)], $noiseColor);
}
}
} /**
* 画一条由两条连在一起构成的随机正弦函数曲线作干扰线(你可以改成更帅的曲线函数)
*
* 高中的数学公式咋都忘了涅,写出来
* 正弦型函数解析式:y=Asin(ωx+φ)+b
* 各常数值对函数图像的影响:
* A:决定峰值(即纵向拉伸压缩的倍数)
* b:表示波形在Y轴的位置关系或纵向移动距离(上加下减)
* φ:决定波形与X轴位置关系或横向移动距离(左加右减)
* ω:决定周期(最小正周期T=2π/∣ω∣)
*
*/
private function _writeCurve() {
$px = $py = 0; // 曲线前部分
$A = mt_rand(1, $this->imageVerifyH/2); // 振幅
$b = mt_rand(-$this->imageVerifyH/4, $this->imageVerifyH/4); // Y轴方向偏移量
$f = mt_rand(-$this->imagimageVerifyHeH/4, $this->imageVerifyH/4); // X轴方向偏移量
$T = mt_rand($this->imageVerifyH, $this->imageW*2); // 周期
$w = (2* M_PI)/$T; $px1 = 0; // 曲线横坐标起始位置
$px2 = mt_rand($this->imageW/2, $this->imageW * 0.8); // 曲线横坐标结束位置 for ($px=$px1; $px<=$px2; $px = $px + 1) {
if ($w!=0) {
$py = $A * sin($w*$px + $f)+ $b + $this->imageVerifyH/2; // y = Asin(ωx+φ) + b
$i = (int) ($this->fontSize/5);
while ($i > 0) {
imagesetpixel($this->_image, $px + $i , $py + $i, $this->_color); // 这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出(不用这while循环)性能要好很多
$i--;
}
}
}
} /* 加密验证码 */
private function authcode($str){
$key = substr(md5($this->seKey), 5, 8);
$str = substr(md5($str), 8, 10);
return md5($key . $str);
} /**
* 绘制背景图片
* 注:如果验证码输出图片比较大,将占用比较多的系统资源
*/
private function _background() {
$path = dirname(__FILE__).'/Verify/bgs/';
$dir = dir($path); $bgs = array();
while (false !== ($file = $dir->read())) {
if($file[0] != '.' && substr($file, -4) == '.jpg') {
$bgs[] = $path . $file;
}
}
$dir->close(); $gb = $bgs[array_rand($bgs)]; list($width, $height) = @getimagesize($gb);
// Resample
$bgImage = @imagecreatefromjpeg($gb);
@imagecopyresampled($this->_image, $bgImage, 0, 0, 0, 0, $this->imageW, $this->imageH, $width, $height);
@imagedestroy($bgImage);
}
}
控制器 /Application/Home/Controller/PostBarController.class.php
<?php namespace Home\Controller;
use Think\Controller;
use Home\Common\VerifyPostBar; class PostBarVerifyController extends Controller { // 界面
public function index() {
header('Content-type:text/html;charset=utf-8');
$this->display();
} // 验证
public function check_verify($code) { $verify = new VerifyPostBar();
if(!$verify->check($code)) {
return 400;
} else {
return 200;
}
} // 准备验证码字符
public function prepare_code() {
// 验证码的长度
$length = 4;
// 验证码选区长度
$selects = 12; // 相近的汉字为一组,从6组36个汉字中抽出4组12个汉字组成验证码图片组
$zhSet = array(
array(
'已','己','乙','巳','九','走'
),
array(
'田','由','甲','申','白','日'
),
array(
'鱼','渔','俞','喻','瑜','愈'
),
array(
'请','清','情','青','晴','蜻'
),
array(
'宝','玉','穴','必','空','控'
),
array(
'子','仔','籽','孜','吱','资'
)
); $tmp = array();
$count = count($zhSet);
$tmp = $this->rand(0, $count - 1, 4); // 随机生成4个不重复的数(0-5组里面选出4组)作为下标
$chars = array();
foreach($tmp as $key => $val) {
$chars[] = $this->choose($zhSet, $val, 3);// 每组3个数
} // 从每组一维数组中选出一个组成长度为4的验证码
foreach($chars as $key => $val) {
$k = mt_rand(0, count($val) - 1);
$code[] = $val[$k]; // 验证码
unset($chars[$key][$k]);
} // dump($code);
// dump($chars);die; // 把数组合并成一维数组
$characters = array();
foreach($chars as $key => $val) {
foreach($val as $k => $v) {
$characters[] = $v;
}
} // 备选验证码区数组
$code_area_array = array_merge($code, $characters); shuffle($code_area_array);
// 备选验证码区字符串
$code_area = implode('', $code_area_array);
$code = implode('', $code); $codes['code_area'] = $code_area;
$codes['code_area_array'] = $code_area_array;
$codes['code'] = $code;
$codes['characters'] = $characters;
$codes['length'] = $length; $_SESSION['code_area_array'] = $code_area_array; return $codes; } // 显示验证码
public function verify() { $codes = $this->prepare_code(); $conf = array(
'useZh' => true,
'zhSet' => $codes['code'],
'code_area' => $codes['code_area'],
'length' => $codes['length'], // 验证码长度(汉字个数)
'rows' => 3, //备选区域3行
'area_length'=> mb_strlen($codes['code_area'], 'utf-8'), // 备选区域汉字个数
'fontSize' => 20,
'imageW' => 320,
'imageH' => 600,
'imageVerifyH' => 45, // 4字验证码区域高度
);
$verify = new VerifyPostBar($conf);
$verify->entryProcess();
} // 从一组连续的数字中选出不重复的个数
// @param $start 数字的开始值
// @param $end 数字的结束值
// @param $count 选出的个数
public function rand($start, $end, $count) {
$tmp = range($start, $end);
$tmp = array_rand($tmp, $count);
return $tmp;
} // 从每组汉字(一组6个)中选出n(4)个
// @param $array 二维数组
// @param $key 数组 $array 的下标
// @param $n 选出几个
public function choose($array, $key, $n) {
$arr = $array[$key];
$count = count($arr);
$tmp_key = $this->rand(0, $count - 1, $n);
$chars = array();
foreach($tmp_key as $val) {
$chars[] = $arr[$val];
}
return $chars;
} // 记录点击次数,如果次数达到4次就做出判断,验证码输入是否正确
public function count_ckick() { session_start(); // 坐标数组
$codes = $_SESSION['code_area_array']; $xy = array(
'line1_y'=>array(
'x1'=>0,
'x2'=>1,
'x3'=>2,
'x4'=>3,
),
'line2_y'=>array(
'x1'=>4,
'x2'=>5,
'x3'=>6,
'x4'=>7,
),
'line3_y'=>array(
'x1'=>8,
'x2'=>9,
'x3'=>10,
'x4'=>11,
)
); if(! isset($_POST['clear']) || $_POST['clear'] != 1) {
$_SESSION['count'] = $count = $_POST['count']; if($count > 4) {
$_SESSION['count'] = 4;
} else {
// 记录选择的验证码文字
$x = $_POST['x'];
$y = $_POST['y']; foreach($xy as $key => $val) {
foreach($val as $k => $v) {
if($y == $key) {
if($x == $k) {
$code_key = $codes[$v];
}
}
}
}
}
if(! isset($_SESSION['input_code'])) {
$_SESSION['input_code'] = $code_key;
} else {
$_SESSION['input_code'] .= $code_key;
} $return = '点击了 '.$_SESSION['count'].' 次, 选中的汉字是: '.$code_key.' 输入的验证码是: '.$_SESSION['input_code']; if($count == 4) {
$code = $this->check_verify($_SESSION['input_code']);
if($code == 200) {
$return .= ' 输入正确';
} else {
$return .= ' 输入错误';
}
}
echo $return;
} else { // 清除点击次数
$_SESSION['count'] = 0;
unset($_SESSION['input_code']);
echo '成功清除了点击次数,点击次数为',$_SESSION['count'],'次';
}
} // 获取session中记录的点击次数
public function record_click() {
session_start();
if(! isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
echo $_SESSION['count'];
} // 修改点击记录数
public function update_click() {
session_start();
if(! isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
} else {
$newcount = $_SESSION['count'] + $_POST['times'];
if($newcount < 0) {
$_SESSION['count'] = 0;
unset($_SEIION['input_code']);
} else {
$_SESSION['count'] = $newcount;
$_SESSION['input_code'] = mb_substr($_SESSION['input_code'], 0, -1, 'utf-8');
}
}
echo '点击数是:'.$_SESSION['count'].' 验证码是:'.$_SESSION['input_code'];
}
}
视图 /Applicable/Home/View/PostBarVerify/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#verify_area {
width:600px;
height: 400px;
position: relative;
padding:10px;
}
h1 {
font-size:16px;
font-family: "微软雅黑";
color: #999;
text-indent: 30px;
}
#notice {
position: relative;
top: 95px;
left: 30px;
color: #666;
display: block;
z-index: 2;
}
#buttons {
width: 350px;
height: 150px;
position: relative;
top: 110px;
left: 20px;
z-index: 2;
padding: 0;
}
#verify_pic {
position: relative;
top: -150px;
}
.button {
display: inline-block;
cursor: pointer;
margin: -15px 12px 15px 5px;
width: 60px;
height: 45px;
border: 1px solid #E0E0E0;
border-bottom-color: #BFBFBF;
outline: 0;
background: -ms-linear-gradient(top,#fff,#f5f5f5);
background: -webkit-gradient(linear,left top,left bottom,from(#fff),to(#f5f5f5));
background: -moz-linear-gradient(top,#fff,#fafafa);
filter: progid:DXImageTransform.Microsoft.Gradient(gradientType=0, startColorStr=#FFFFFF, endColorStr=#F5F5F5);
-webkit-opacity: 0.3;
-moz-opacity: 0.3;
-khtml-opacity: 0.3;
opacity: .3;
filter:alpha(opacity=30);
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=30);
zoom: 1;
}
#verify_title {
text-indent: 30px;
position: relative;
top: 25px;
font-family: "微软雅黑";
color: #999;
}
#verify {
width: 200px;
height: 34px;
position: relative;
top: 0px;
left: 80px;
border: 1px solid #ccc;
}
.verify {
width: 40px;
height: 34px;
border-right: 1px solid #ccc;
float: left;
background-repeat: no-repeat;
}
.verify_last { border-right: 0 }
.cls { clear: both }
.hid { display: none; }
#delete {
position: relative;
left: 162px;
width: 39px;
height: 34px;
background: url('__PUBLIC__/Images/delete.png') 0 0 no-repeat;
cursor: pointer;
}
.addbg {
background-image: url("__PUBLIC__/Images/verifyImage.png")
}
</style>
<script src="__PUBLIC__/Js/jquery-1.9.1.min.js"></script>
</head>
<body>
<div id="verify_area">
<form action="{:U('Home/PostBarVerify/check_verify','','')}" method="post" id="form">
<h1>点击验证码图片换一张</h1>
<div>
<div id="verify_title">验证码</div>
<div id="verify">
<div id="verify1" class="verify"></div>
<div id="verify2" class="verify"></div>
<div id="verify3" class="verify"></div>
<div id="verify4" class="verify verify_last"></div>
<div id="delete"></div>
<div class="cls"></div>
</div>
</div>
<p id="notice">点击框内文字输入上图中汉字</p>
<div id="buttons">
<for start="0" end="3" name="i">
<br />
<for start="0" end="4" name="j">
<div class="button" x="x{$j+1}" y="line{$i+1}_y"></div>
</for>
</for>
</div>
<img id="verify_pic" src='' style="cursor: pointer;" alt="">
<span class="hid" id="verify_url">{:U('Home/PostBarVerify/verify','','')}</span>
</form>
</div>
</body>
<script>
$(function(){ // 加载或刷新时清空session计数
$count = 0;
clear_count(); $xy = {
"line1_y" : -112, // 备选验证码第一行y坐标
"line2_y" : -165, // 备选验证码第二行y坐标
"line3_y" : -212, // 备选验证码第三行y坐标
"x1" : -35, // 备选验证码每行第一个字x坐标
"x2" : -114, // 备选验证码每行第二个字x坐标
"x3" : -195, // 备选验证码每行第三个字x坐标
"x4" : -276 // 备选验证码每行第四个字x坐标
}; $verify_url = $("#verify_url").html(); // 验证码请求地址
$src = $verify_url + '?' + Math.random();
change_verify($src); // 载入页面时加载验证码 $("#verify_pic").click(function(){ // 点击验证码时更换验证码
change_verify($src);
// 清除验证码
$(".verify").css('background-image', '');
clear_count($count);
}); function clear_count() {
// 清空session计数
$.ajax({
url: '{:U("/Home/PostBarVerify/count_ckick")}',
type: 'post',
data: {
"clear": 1
},
success: function(data) {
console.log(data);
}
});
} // 更换验证码
function change_verify($src) { var flag = 0;
// 请求验证码地址生成验证码图片
$.ajax({
url: $src,
async: false,
success: function() {
flag = 1;
}
}); if(flag == 1) {
$('#verify_pic').attr('src', $src); // 验证码图片图片
}
} // 点击备选区选择验证码
$('.button').click(function() { // 查询session中保存的count
$.ajax({
url: '{:U("/Home/PostBarVerify/record_click")}',
async: false,
success: function(data) {
$count = data;
}
}); $count++;
if($count > 4) {
// return false;
} $.ajax({ // 记录点击次数以及点击的文字
url: '{:U("/Home/PostBarVerify/count_ckick")}',
type: 'post',
data: {
"count": $count,
"x": $(this).attr("x"),
"y": $(this).attr("y")
},
success: function(data) {
if(data != '') {
console.log(data);
}
}
}); $x = $(this).attr('x');
$y = $(this).attr('y'); choose_verify($xy, $x, $y, $count);
}); // 生成每次点击验证码的坐标,填充到验证码
function choose_verify($xy, $x, $y) { $x = $xy[$x] + 'px';
$y = $xy[$y] + 'px'; // 填充验证码
$('#verify'+$count).css({
'background-position-x': $x,
'background-position-y': $y
}).addClass('addbg');
} // 删除验证码
$('#delete').click(function(){ $.ajax({
url: '{:U("Home/PostBarVerify/record_click")}',
type: 'post',
async: false,
success: function(data) {
if(data == 0) {data = 1;}
$i = data;
}
}); $('#verify'+$i).removeClass('addbg');console.log('#verify'+$i);
$i--;
// 修改计数,清除session
$.ajax({
url: '{:U("Home/PostBarVerify/update_click")}',
type: 'post',
data: {
'times': -1
},
success: function(data) {
console.log(data);
}
});
$count--;
});
});
</script>
</html>
演示
初始状态:
输入验证码:
输入完成,返回结果,错误时:
输入完成,返回结果,正确时:
删除验证码:
刷新验证码:
参考:
CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
PHP 实现“贴吧神兽”验证码的更多相关文章
- 设置HttponlyCookie解决mshtml编程无法获取验证码图片流
最近给客户做的项目有一个新需求,客户需要在打开的IE浏览器中做自动登录,登录的页面上有神兽验证码.解决验证码的方案是找第三方平台打码.这样就有一个问题,如何把正确的验证码传给第三方打码平台. 大家都知 ...
- springboot security+redis+jwt+验证码 登录验证
概述 基于jwt的token认证方案 验证码 框架的搭建,可以自己根据网上搭建,或者看我博客springboot相关的博客,这边就不做介绍了.验证码生成可以利用Java第三方组件,引入 <dep ...
- .net点选验证码实现思路分享
哈哈好久没冒泡了,最进看见点选验证码有点意思,所以想自己写一个. 先上效果图 如果你被这个效果吸引了就请继续看下去. 贴代码前先说点思路: 1.要有一个汉字库,并按字形分类.(我在数据库里是安部首分类 ...
- 【探索】无形验证码 —— PoW 算力验证
先来思考一个问题:如何写一个能消耗对方时间的程序? 消耗时间还不简单,休眠一下就可以了: Sleep(1000) 这确实消耗了时间,但并没有消耗 CPU.如果对方开了变速齿轮,这瞬间就能完成. 不过要 ...
- TODO:Laravel增加验证码
TODO:Laravel增加验证码1. 先聊聊验证码是什么,有什么作用?验证码(CAPTCHA)是"Completely Automated Public Turing test to te ...
- PHP-解析验证码类--学习笔记
1.开始 在 网上看到使用PHP写的ValidateCode生成验证码码类,感觉不错,特拿来分析学习一下. 2.类图 3.验证码类部分代码 3.1 定义变量 //随机因子 private $char ...
- 随手记_C#验证码
前言 最近在网上偶然看见一个验证码,觉得很有意思,于是搜了下,是使用第三方实现的,先看效果: 总体来说效果还是可以的,官方提供的SDK也比较详细,可配置性很高.在这里在简单啰嗦几句使用方式: 使用步骤 ...
- WPF做12306验证码点击效果
一.效果 和12306是一样的,运行一张图上点击多个位置,横线以上和左边框还有有边框位置不允许点击,点击按钮输出坐标集合,也就是12306登陆的时候,需要向后台传递的参数. 二.实现思路 1.获取验证 ...
- 零OCR基础6行代码实现C#验证码识别
这两天因为工作需要,要到某个网站采集信息,一是要模拟登陆,二是要破解验证码,本想用第三方付费打码,但是想想网上免费的代码也挺多的,于是乎准备从网上撸点代码下来,谁知道,撸了好多个都不行,本人以前也没接 ...
随机推荐
- Multiload-ng
导读 Multiload-ng是一个 GTK2 图形化系统监视器应用,可集成到 Xfce.LXDE 及 MATE 的桌面面板中, 它 fork 自原来的 GNOME Multiload 应用.它也可以 ...
- 利用js刷新页面方法
1,reload 方法,该方法强迫浏览器刷新当前页面. location.reload(force) 如果该方法没有规定参数,或者参数是 false,它就会用 HTTP 头 If-Modified-S ...
- How-to-uninstall-Meteor // install Meteor manually
How-to-uninstall-Meteor : http://www.uninstallapp.com/article/How-to-uninstall-Meteor-.html install ...
- java5
1:final关键字(掌握) (1)是最终的意思,可以修饰类,方法,变量. (2)特点: A:它修饰的类,不能被继承. B:它修饰的方法,不能被重写. C:它修饰的变量,是一个常量. (3)面试相关: ...
- Angularjs 脏值检测
文章转自:http://www.ituring.com.cn/article/39865 构建自己的AngularJS,第一部分:Scope和Digest 原文链接:http://teropa.inf ...
- Java 读写XML
package dome4jTest; import java.io.FileWriter; import java.io.IOException; import java.net.URL; impo ...
- percona-toolkit 之 【pt-online-schema-change】说明
背景: MySQL 大字段的DDL操作:加减字段.索引.修改字段属性等,在5.1之前都是非常耗时耗力的,特别是会对MySQL服务产生影响.在5.1之后随着Plugin Innodb的出现在线加索引的提 ...
- 命令行环境下简单实用的工具——重定向&管道
如果你对管道和重定向应用自如了,无需继续往下看.本文虽然以windows上cmd命令行环境演示,但同样适用于Unix/Linux等平台. 引言 关于管道和重定向,最初是在刘汝佳的<算法竞赛入门经 ...
- CCProxy二级代理上网设置
假如电脑A可以通过代理服务器上网,B电脑又可以连接A电脑,那么A电脑可以作为二级代理服务器进行上网,需要设置如下: 1.在A电脑上安装CCProxy,以v8.0为例 2.选择设置->高级 3.启 ...
- 各种浏览器的Hack写法(chrome firefox ie等)
Hack是针对不同的浏览器去写不同的CSS样式,从而让各浏览器能达到一致的渲染效果,那么针对不同的浏览器写不同的CSS CODE的过程,就叫CSS HACK,同时也叫写CSS Hack. 然后将Hac ...