【PHP】一步一步實現驗證碼

背景

驗證碼就是把一串隨機產品的數字動態生成一幅圖片,再加上干擾元素。此時用戶可以通過肉眼能識別里面的數字或者字符,但是可以屏蔽機器的自動識別。

很多地方需要用到驗證碼,因為Web網站經常會遇到身份欺騙的攻擊,攻擊者通過在客戶端腳本寫入代碼,寫請求消耗遠遠大于讀請求。大量寫請求的情況,會嚴重耗費系統的資源。所以說驗證碼主要是防止有人利用機器人進行自動批量注冊等行為。

筆者看過了http://www.imooc.com/learn/115
的視頻教程以后非常有感觸,想把實現驗證碼的步驟一步一步的記錄下來。同時最后的時候他封裝成類,可以在之后的工作中進行反復的利用。

其實驗證碼的代碼已經研究了很多次了,但是大部分網上找到的教程都是一次性給出所有的代碼,這樣閱讀的時候很難把握住筆者的開發思路,本教程希望一步一步的截圖上代碼,幫助新人理清思路。

驗證碼的核心技術

首先需要對實現驗證碼的步驟進行分解。主要可以分為如下幾步:

  • 生成驗證碼底圖
  • 生成隨機字符,然后和底圖合并
  • 當用戶輸入的時候,和原內容進行對比校驗。
Paste_Image.png

接下來我們分不同的章節介紹如何實現每一個步驟。

環境

項目 內容
操作系統 windows
環境 xamp

需要啟動Apache,驗證方法是在瀏覽器框里輸入127.0.0.1
如果出現如下的圖片,則啟動成功。


Paste_Image.png

實現驗證碼底圖

首先是通過PHP實現100×30px大小的圖片。
主要使用的函數方法:resource imagecreatetruecolor(int $width, int $height)
在D:\xampp\htdocs下建立project文件夾。新建captcha.php
輸入:

<?php $image = imagecreatetruecolor(100,30);//生成資源 $bgcolor = imagecolorallocate($image , 255,255,255);//#ffffff,為一幅圖像分配顏色 imagefill($image , 0 , 0 , $bgcolor);//左上角,區域填充 header("content-type:image/png"); imagepng($image); imagedestroy($image); ?>
在瀏覽器輸入框輸入http://127.0.0.1/project/captcha.php

Paste_Image.png

結果是一片大白。

下面解釋一下里面涉及到的函數:

項目 內容
imagecreatetruecolor 生成空白的畫布
imagecolorallocate 分配顏色
imagefill 填充顏色
header 發送HTTP頭
imagepng 以png格式進行導出
imagedestory 輸出結束的時候記得回收資源

為了表明各函數用法,特將PHP手冊中的詳細用法摘錄如下:

  • imagecreatetruecolor — 新建一個真彩色圖像
    resource imagecreatetruecolor ( int $width , int $height )
  • imagecolorallocate — 為一幅圖像分配顏色
    int imagecolorallocate ( resource $image , int $red , int $green , int $blue )
    第一次對 imagecolorallocate() 的調用會給基于調色板的圖像填充背景色,即用 imagecreate() 建立的圖像。
    其他red,green,blue對應RGB值
  • imagefill — 區域填充
    bool imagefill ( resource $image , int $x , int $y , int $color )
    imagefill() 在 image 圖像的坐標 x,y(圖像左上角為 0, 0)處用 color 顏色執行區域填充(即與 x, y 點顏色相同且相鄰的點都會被填充)。
  • header — 發送原生 HTTP 頭
    void header ( string $string [, bool $replace = true [, int $http_response_code ]] )
    請注意 header() 必須在任何實際輸出之前調用
  • imagepng — 以 PNG 格式將圖像輸出到瀏覽器或文件
    bool imagepng ( resource $image [, string $filename ] )
  • imagedestroy — 銷毀圖片資源
    bool imagedestroy ( resource $image )

注意事項:

  • 依賴于GD擴展,輸出圖片前必須提前輸出圖片header信息
  • 默認輸出為黑色背景。

實現數字驗證碼

在上一章里面我們已經新建了一張畫布,相當于把整個框架搭起來了,本章的主要目的是在上面加上隨機的數字。
給圖片加上數字,主要使用imagestring()方法。

imagestring — Draw a string horizontally
bool imagestring ( resource $image , int $font , int $x , int $y , string $string , int $color )

  • font:表示字體,
  • x,y:表示位置

從上面這個函數的參數可以看出,我們需要給出生成隨機驗證碼數字的字體,位置,內容和顏色。
字體是死的,可以直接規定大小。

因為要生成4個隨機數字,可以使用一個for循環for ($i = 0 ; $i < 4 ; $i++)。

下面討論怎么獲得位置信息:
可以把長度100分成4份,所以每個數字的位置是($i * 100 / 4 ),然后加上隨機的offset,可以得到
$x = ($i * 100 / 4 ) + rand (5,10);

內容通過:$fontContent = rand (0,9);獲得。

最后是怎么獲得隨機的顏色:
對于imagecolorallocate()這個函數而言,只需要獲得隨機的RGB值,就可以實現隨機的顏色了。為了更加醒目,我們限定隨機RGB值的范圍為0~120,因為是深色區間。

$fontColor = imagecolorallocate($image , rand(0,120) , rand(0,120), rand(0,120));//0~120是深色區間。

下面加上生成隨機數字的代碼段,在imagefill()那行下面加入:
<?php $image = imagecreatetruecolor(100,30);//生成資源 $bgcolor = imagecolorallocate($image , 255,255,255);//#ffffff,為一幅圖像分配顏色 imagefill($image , 0 , 0 , $bgcolor);//左上角,區域填充 // 生成隨機數字 for ($i = 0 ; $i < 4 ; $i++){ $fontSize = 6; $fontColor = imagecolorallocate($image , rand(0,120) , rand(0,120), rand(0,120));//0~120是深色區間。 $fontContent = rand (0,9); // 坐標 $x = ($i * 100 / 4 ) + rand (5,10);//總寬度100,放4個數字。 $y = rand (5 , 10); imagestring ($image,$fontSize,$x,$y,$fontContent,$fontColor); } header("content-type:image/png"); imagepng($image); imagedestroy($image); ?>

在地址欄里面輸入127.0.0.1/project/captcha.php

Paste_Image.png

可以看出生成了4個隨機的數字。

增加干擾元素

為了防止被機器輕易的讀出來,可以增加干擾的元素。
先增加干擾的小點,用到函數
bool imagesetpixel(resource $image , int $x , int $y , int $color)

首先看點的位置怎么得到。
既然是隨機生成用來干擾的點,那么可以在整個畫布隨機的跑,所以x = rand (1 , 99); y = rand (1 , 29)
而點的顏色注意要比字的淺,所以在50~200中選。

上代碼,增加200個點。

<?php $image = imagecreatetruecolor(100,30);//生成資源 $bgcolor = imagecolorallocate($image , 255,255,255);//#ffffff,為一幅圖像分配顏色 imagefill($image , 0 , 0 , $bgcolor);//左上角,區域填充 for ($i = 0 ; $i < 4 ; $i++){ $fontSize = 6; $fontColor = imagecolorallocate($image , rand(0,120) , rand(0,120), rand(0,120));//0~120是深色區間。 $fontContent = rand (0,9); // 坐標 $x = ($i * 100 / 4 ) + rand (5,10);//總寬度100,放4個數字。 $y = rand (5 , 10); imagestring ($image,$fontSize,$x,$y,$fontContent,$fontColor); } for ($i = 0 ; $i < 200 ; $i++){ $pointColor = imagecolorallocate ($image , rand (50,200),rand(50,200),rand(50,200));//顏色要比數字的淺。 imagesetpixel ($image , rand (1,99),rand(1,29),$pointColor);//生成的點不要超過畫布。 } header("content-type:image/png"); imagepng($image); imagedestroy($image); ?>
依舊看看效果:

Paste_Image.png

再加點隨機的線:
使用方法:bool imageline (resource $image , int $x1 , int $y1 , int $x2 , int $y2 , int $color)
手冊上的解釋是:
Draws a line between the two given points.
也就是說在給出的兩點間畫線。

注意隨機線的顏色比隨機點的顏色要更淺,所以在80~220里面選。
下面給出加隨機線的代碼:
// 生成干擾線 for ( $i = 0 ; $i < 3 ; $i++){ $lineColor = imagecolorallocate($image , rand (80,220),rand(80,220),rand(80,220)); imageline($image , rand (1,99),rand(1,29),rand(1,99),rand(1,29),$lineColor); }
結果如圖:

Paste_Image.png

生成隨機的字母和數字

之前生成的內容只有隨機的數字,還是容易被機器識別出來,所謂道高一尺魔高一丈,對手在加碼,我們也得加碼撒。下面我們在隨機的內容里面加上字母,這樣組合更多,可以更好的屏蔽那些機器人。

首先我們把可能用到的字母和數字放到變量$data里面去,注意可以把容易混淆的字母和數字去掉,比如l和數字1容易混,所以直接干掉。

然后每次隨機的從字符串里面抽一個出來,使用substr函數。
string substr ( string $string , int $start [, int $length ] )
從$string里$start位置抽出$length長的字符。

這樣對原有的代碼進行簡單的修改就可以了。

<?php $image = imagecreatetruecolor(100,30);//生成資源 $bgcolor = imagecolorallocate($image , 255,255,255);//#ffffff,為一幅圖像分配顏色 imagefill($image , 0 , 0 , $bgcolor);//左上角,區域填充 // 生成隨機數字 for ($i = 0 ; $i < 4 ; $i++){ $fontSize = 6; $fontColor = imagecolorallocate($image , rand(0,120) , rand(0,120), rand(0,120));//0~120是深色區間。 // $fontContent = rand (0,9); $data = "abcdefghijkmnopqrstuvwxyz23456789"; // 生成隨機的字母和數字,從$data字符串里面,任意一個位置,取一個字母 $fontContent = substr($data , rand(0,strlen($data)), 1); // 坐標 $x = ($i * 100 / 4 ) + rand (5,10);//總寬度100,放4個數字。 $y = rand (5 , 10); imagestring ($image,$fontSize,$x,$y,$fontContent,$fontColor); } for ($i = 0 ; $i < 200 ; $i++){ $pointColor = imagecolorallocate ($image , rand (50,200),rand(50,200),rand(50,200));//顏色要比數字的淺。 imagesetpixel ($image , rand (1,99),rand(1,29),$pointColor);//生成的點不要超過畫布。 } // 生成干擾線 for ( $i = 0 ; $i < 3 ; $i++){ $lineColor = imagecolorallocate($image , rand (80,220),rand(80,220),rand(80,220)); imageline($image , rand (1,99),rand(1,29),rand(1,99),rand(1,29),$lineColor); } header("content-type:image/png"); imagepng($image); imagedestroy($image); ?>
效果如圖

Paste_Image.png

通過session存儲驗證信息

session是存儲的服務器端的信息,可以把生成的內容保存在服務器端的$_SESSION["authcode"]字段里面。當前端的用戶輸入相應的驗證字符后,和$_SESSION["authcode"]進行對比,如果相同,自然證明輸入正確、

需要在代碼的最頂部加上session_start()

現在要考慮如何保存保存驗證碼的信息,先定義一個$captch_code 的空字符串,每生成一的隨機的數字或者字符,都拼接到上面去。

其實在真實的開發環境下,我們都是用服務器的集群來保存session的,也就是說有可能第一次請求的時候建立的session保存在A服務器上,但是下次需要來拿數據的時候會被分配到B服務器上,所以校驗會失敗。在多服務器的情況下,我們需要考慮集中管理session,比如使用memcache來保存session信息。

<?php session_start(); $image = imagecreatetruecolor(100,30);//生成資源 $bgcolor = imagecolorallocate($image , 255,255,255);//#ffffff,為一幅圖像分配顏色 imagefill($image , 0 , 0 , $bgcolor);//左上角,區域填充 // 生成隨機數字 $captch_code = ""; for ($i = 0 ; $i < 4 ; $i++){ $fontSize = 6; $fontColor = imagecolorallocate($image , rand(0,120) , rand(0,120), rand(0,120));//0~120是深色區間。 // $fontContent = rand (0,9); $data = "abcdefghijkmnopqrstuvwxyz23456789"; // 生成隨機的字母和數字,從$data字符串里面,任意一個位置,取一個字母 $fontContent = substr($data , rand(0,strlen($data)), 1); $captch_code .= $fontContent; // 坐標 $x = ($i * 100 / 4 ) + rand (5,10);//總寬度100,放4個數字。 $y = rand (5 , 10); imagestring ($image,$fontSize,$x,$y,$fontContent,$fontColor); } // 將循環生成的隨機數字保存在$_SESSION里面 $_SESSION['authcode'] = $captch_code; for ($i = 0 ; $i < 200 ; $i++){ $pointColor = imagecolorallocate ($image , rand (50,200),rand(50,200),rand(50,200));//顏色要比數字的淺。 imagesetpixel ($image , rand (1,99),rand(1,29),$pointColor);//生成的點不要超過畫布。 } // 生成干擾線 for ( $i = 0 ; $i < 3 ; $i++){ $lineColor = imagecolorallocate($image , rand (80,220),rand(80,220),rand(80,220)); imageline($image , rand (1,99),rand(1,29),rand(1,99),rand(1,29),$lineColor); } header("content-type:image/png"); imagepng($image); imagedestroy($image); ?>

驗證碼通過表單進行提交

在project文件夾里面新建form.php
輸入
<pre>
<?php?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>確認驗證碼</title>
</head>
</pre>
<body> <form action="./form.php" method="post"> <p>驗證圖片:![](./captcha.php)</p> <p>請輸入圖片中的內容:<input type="text" name="authcode" value=""/></p> <p><input type="submit" value="提交" style="padding:6px 20px;"/></p> </form> </body> </html>

表單提交的內容都會存到$_REQUEST['authcode']里面,所以需要加上驗證表單提交和$_SESSION[‘authcode’]是否相同的代碼。
<pre>
<?php
if (isset($_REQUEST['authcode'])){
session_start();
if($_REQUEST['authcode'] == $_SESSION['authcode']){
echo '<font color="#0000CC">輸入正確</font>';
}else{
echo '<font color = "#CC0000"><b>輸入錯誤</b></font>';
}
exit();
}
?>
</pre>

此時在地址欄輸入127.0.0.1/project/form.php,然后填入驗證碼字符

Paste_Image.png

點擊提交按鈕。

Paste_Image.png

但是如果是輸入全大寫的字母,會輸出“輸入錯誤”的標志。

因為我們在判斷的時候是把原始輸入和服務器保存的進行比較,所以自然需要完全一致才行。
可以把用戶的輸入全部轉換為小寫
<pre>
<?php
if (isset($_REQUEST['authcode'])){
session_start();
if(strtolower(trim($_REQUEST['authcode'])) == $_SESSION['authcode']){
echo '<font color="#0000CC">輸入正確</font>';
}else{
echo '<font color = "#CC0000"><b>輸入錯誤</b></font>';
}
exit();
}
?>
</pre>

動態驗證

之前的代碼存在一個問題,如果出來的驗證碼圖片用戶不能完全分辨得出,就沒有辦法了。在生活中,一般的驗證碼圖片旁邊都會有“看不清?”這樣的提示,點擊的話,會刷新驗證碼。
可以通過三個步驟進行:

  • 增加可點擊的“換一個”文案
  • 用JS選擇器選取圖片
  • 用js修改驗證碼圖片地址
    首先增加文案
    <pre>
    <a href="javascript:void(0)">換一個?</a>
    </pre>
    為了方便選取圖片,給img加上id屬性,使用document.getElementById('captch_img')獲得圖片,然后用新的圖片對他進行賦值,注意可以加上一段隨機數字。
    <pre>
    <?php
    if (isset($_REQUEST['authcode'])){
    session_start();
    if(strtolower(trim($_REQUEST['authcode'])) == $_SESSION['authcode']){
    echo '<font color="#0000CC">輸入正確</font>';
    }else{
    echo '<font color = "#CC0000"><b>輸入錯誤</b></font>';
    }
    exit();
    }
    ?>
    <!doctype html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>確認驗證碼</title>
    </head>
    <body>
    <form action="./form.php" method="post">
    <p>驗證圖片:<img id="captcha_img" border="1" src="./captcha.php?r=<?php echo rand();?>" width="100" heigh="30">
    <a href="javascript:void(0)" onclick="document.getElementById('captcha_img').src='./captcha.php?r='+Math.random()">換一個?</a>
    </p>
    <p>請輸入圖片中的內容:<input type="text" name="authcode" value=""/></p>
    <p><input type="submit" value="提交" style="padding:6px 20px;"/></p>
    </form>
    </body>
    </html>
    </pre>

至此驗證碼的功能基本都實現了,下面主要進行類的封裝,以后可以多次的復用。

驗證碼類的封裝

首先考慮通用的驗證碼類里面有那些元素:

<pre>
class Vcode {
private $width; //驗證碼圖片的寬度
private $height; //驗證碼圖片的高度
private $codeNum; //驗證碼字符的個數
private $disturbColorNum; //干擾元素數量
private $checkCode; //驗證碼字符
private $image; //驗證碼資源
}
</pre>

然后寫構造方法,主要用來實例化驗證碼對象,并為一些成員屬性初使化 。
在寫構造方法之前,我們新定義一個內部私有方法createCheckCode(),隨機生成用戶指定個數的字符串,去掉了容易混淆的字符oOLlz和數字012
<pre>
private function createCheckCode(){
$data="3456789abcdefghijkmnpqrstuvwxy";
for($i=0; $i<$this->codeNum; $i++) {
// $char = $code{rand(0,strlen($code)-1)};
$fontContent = substr($data , rand(0,strlen($data)), 1);
$captch_code .= $fontContent;
}
return $captch_code;
}
</pre>

然后開始寫構造函數:
<pre>
/**
* 構造方法用來實例化驗證碼對象,并為一些成員屬性初使化
* @param int $width 設置驗證碼圖片的寬度,默認寬度值為80像素
* @param int $height 設置驗證碼圖片的高度,默認高度值為20像素
* @param int $codeNum 設置驗證碼中字母和數字的個數,默認個數為4個
/
function __construct($width=80, $height=20, $codeNum=4) {
$this->width = $width;
$this->height = $height;
$this->codeNum = $codeNum;
$number = floor($height
$width/15);
//如果驗證碼字符過多,則需要減少干擾點的數量
if($number > 240-$codeNum)
$this->disturbColorNum = 240-$codeNum;
else
$this->disturbColorNum = $number;
$this->checkCode = $this->createCheckCode();
}
</pre>

我們之前講過輸出圖像有幾個步驟,首先新建畫布,然后生成干擾點,再加上隨機的字符,最后輸出。可以把每個步驟包裝成一個方法,然后在outImg()里面統一調用。

  • 新建畫布
    <pre>
    /* 內部使用的私有方法,用來創建圖像資源,并初使化背影 */
    private function getCreateImage(){
    $this->image = imagecreatetruecolor($this->width,$this->height);

          $backColor = imagecolorallocate($this->image, rand(225,255),rand(225,255),rand(225,255)); 
          
          @imagefill($this->image, 0, 0, $backColor); 
          
      }
    

</pre>

  • 設置干擾元素
    <pre>
    /* 內部使用的私有方法,設置干擾像素,向圖像中輸出不同顏色的點 */
    private function setDisturbColor() {
    // 畫隨機點
    for($i=0; $i <= $this->disturbColorNum; $i++) {
    $color = imagecolorallocate($this->image, rand(50,200), rand(50,200), rand(50,200));
    imagesetpixel($this->image,rand(1,$this->width-2),rand(1,$this->height-2),$color);
    }
    // 畫隨機線
    for($i=0; $i<10; $i++){
    $color=imagecolorallocate($this->image,rand(80,220),rand(80,220),rand(80,220));
    imageline($this->image,rand(-10,$this->width),rand(-10,$this->height),rand(30,300),rand(20,200),55,44,$color);
    }
    }
    </pre>

  • 在圖片上寫字

<pre>
/* 內部使用的私有方法,隨機顏色、隨機擺放、隨機字符串向圖像中輸出 /
private function outputText() {
for ($i=0; $i<=$this->codeNum; $i++) {
$fontcolor = imagecolorallocate($this->image, rand(0,128), rand(0,128), rand(0,128));
$fontSize = rand(3,5);
$x = floor($this->width/$this->codeNum)
$i+3;
$y = rand(0,$this->height-imagefontheight($fontSize));
imagechar($this->image, $fontSize, $x, $y, $this->checkCode{$i}, $fontcolor);
}
}
</pre>

  • 輸出圖像,

<pre>
/* 內部使用的私有方法,自動檢測GD支持的圖像類型,并輸出圖像 */
private function outputImage(){
if(imagetypes() & IMG_GIF){
header("Content-type: image/gif");
imagegif($this->image);
}elseif(imagetypes() & IMG_JPG){
header("Content-type: image/jpeg");
imagejpeg($this->image, "", 0.5);
}elseif(imagetypes() & IMG_PNG){
header("Content-type: image/png");
imagepng($this->image);
}elseif(imagetypes() & IMG_WBMP){
header("Content-type: image/vnd.wap.wbmp");
imagewbmp($this->image);
}else{
die("PHP不支持圖像創建!");
}
}
</pre>

  • 使用outImg()函數統一起來

<pre>
/* 內部使用的私有方法,用于輸出圖像 */
private function outImg(){
$this->getCreateImage();
$this->setDisturbColor();
$this->outputText();
$this->outputImage();
}
</pre>

  • 向服務器SESSION中保存驗證碼
    <pre>
    /**
    * 用于輸出驗證碼圖片,也向服務器的SESSION中保存了驗證碼,使用echo 輸出對象即可
    /
    function __toString(){
    /
    加到session中, 存儲下標為code */
    $_SESSION["code"] = strtoupper($this->checkCode);
    $this->outImg();
    return '';
    }
    </pre>

  • 析構函數

<pre>
/* 析構方法,在對象結束之前自動銷毀圖像資源釋放內存 */
function __destruct(){
imagedestroy($this->image);
}
</pre>

至此驗證碼類已經完成,只要直接輸出對象,就可以向瀏覽器中輸出圖片,可以在表單中使用。

在提交驗證碼到服務器的時候,已經轉為了大寫,需要在驗證的時候把瀏覽器提交的也轉換為大寫。

應用驗證碼類

新建imgcode.php文件,使用session_start()開啟回話控制,同時創建類的對象。
此時如果使用echo輸出,同時會自動將驗證碼字符串保存在服務器中。

<pre>
<?php
/**
file:imgcode.php
用于請求時,通過驗證碼類的對象向客戶端輸出圖片
*/
session_start(); //開啟SESSION,會使用$_SESSION["code"]在服務器中保存驗證碼

require_once('captch.class.php');    //包含驗證碼所在的類文件
echo new Vcode();                   //創建驗證碼對象,并直接被輸出自動調用魔術__toString()方法

</pre>

構造表單,應用驗證碼

在form.php中,包含輸入表單和匹配驗證碼兩部分。

<pre>
<?php
/** form.php 用于輸出用戶操作表單和驗證用戶的輸入 /
session_start(); //開啟SESSION
if(isset($_POST['submit'])){ //判斷用戶提交后執行
/
判斷用戶在表單中輸入的字符串和驗證碼圖片中的字符串是否相同 /
if(strtoupper(trim($_POST["code"])) == $_SESSION['code']){ //如果驗證碼輸出成功
echo '驗證碼輸入成功
'; //輸出成功的提示信息
}else{ //如果驗證碼輸入失敗
echo '<font color="red">驗證碼輸入錯誤??!</font>
'; //輸出失敗的輸入信息
}
}
?>
<html>
<head>
<title>Image</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<script>
/
定義一個JavaScript函數,當單擊驗證碼時被調用,將重新請求并獲取一個新的圖片 /
function newgdcode(obj,url) {
/
后面傳遞一個隨機參數,否則在IE7和火狐下,不刷新圖片 */
obj.src = url+ '?nowtime=' + new Date().getTime();
}
</script>
</head>
<body> ![](imgcode.php) <form method="POST" action="form.php"> <input type="text" size="4" name="code" /> <input type="submit" name="submit" value="提交"> </form> </body> </html>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,268評論 2 375

推薦閱讀更多精彩內容