表单验证类 PHP

验证类

1.提供两种调用方式
Validator::ValidatorInput 验证input数组
Validator::ValidatorInputRow 验证一行
2.验证规则两种写法
竖线分隔:ruler = 'type=int|required|min=3'; 数组模式 :ruler = array('type'=>'int','required'=>true,'min'=>10,);

3.扩展
自定义 {$type}Validator 方法 扩展验证类

使用示例

$arrInput = array(
    'orderId' => '3',
    'status' => '3',
);
$arrValidationRule = array(
    'orderId' => 'type=int|required|min=3',// int 必须 最小值 3
    'status' => 'type=int|status|enum=1,2,3,4|cnName=状态',// string  非必需   枚举[1,2,3,4]   中文名= 状态
);
Validator::ValidatorInput($arrInput, $arrValidationRule);

---
// int 必须 最小值 3
Validator::ValidatorInputRow($orderId,'type=int|required|min=3','orderId');

// string  非必需   枚举[1,2,3,4]   中文名= 状态

Validator::ValidatorInputRow($status,'type=string|status|enum=1,2,3,4|cnName=状态','status');

验证类

<?php

/**
 * Created by PhpStorm.
 * Date: 2018/1/11  16:54
 */
class Validator {
    const  ERR_CODE_INPUT_ERROR = 4000001;
    const  ERR_CODE_INPUT_REQUIRED = 4000002;
    const  ERR_CODE_INPUT_TYPE = 4000003;

    const  ERR_CODE_CHECK_REFER = 4000100;

    public static $MSG = array(
        self::ERR_CODE_INPUT_ERROR    => '参数错误',
        self::ERR_CODE_INPUT_REQUIRED => '必须的',
        self::ERR_CODE_INPUT_TYPE     => '类型错误',
        self::ERR_CODE_CHECK_REFER    => 'Refer验证',
    );

    /**
     * Validator   @desc   成批验证输入
     * @param $arrInput
     *                            array(
     *                            'k1'=>'v1',
     *                            'k2'=>'v2',
     *                            'k3'=>'v3',
     *                            );
     * @param $arrValidationRule
     *                            支持两种验证规则输入格式  字符串传参 和 输出传参
     *
     * 字符串传参
     * array(
     *    'k1'=>'required|type=string|format=date|pattern=#^1[3456789]\d{9}$#|min=1|max=1|enum=1,2,3|nameCn=中文名称',
     *    'k2'=>'type=string',
     *    'k3'=>'enum=1,2,3',
     * );
     *    ||   ||   ||
     * 输出传参
     * array(
     *     'k1'=>array(
     *         'required',
     *         'type'=>'string',
     *         'format'=>'date',
     *         'pattern'=>'#^1[3456789]\d{9}$#',
     *         'min'=>'1',
     *         'max'=>'2',
     *         'enum'=>array('1','2','3'),
     *     ),
     *     'k2'=>array(
     *         'type'=>'string'
     *     ),
     *     'k3'=>array(
     *         'enum'=>array('1','2','3'),
     *     ),
     * );
     * @param bool $checkRequired 是否进行必要验证
     * @param bool $isGetMessage  是否返回message false 不返回
     * @return array|bool
     */
    static public function ValidatorInput($arrInput, $arrValidationRule, $checkRequired = true, $GetMessage = false) {
        $errMessages = array();

        foreach ($arrValidationRule as $key => $val) {
            try {
                $arrRules = self::ruleTransform($val);
                $name = (isset($arrRules['nameCn']) && (!empty($arrRules['nameCn']))) ? $arrRules['nameCn'] : $key;

                //是否需要进行必要的参数校验
                if (($checkRequired === true) && isset($arrRules['required'])) {
                    $value = isset($arrInput[$key])?$arrInput[$key]:'';
                    $checkRequired = self::requiredValidator($value,true);
                    if (!$checkRequired) {
                        throw new Exception(self::$MSG[self::ERR_CODE_INPUT_REQUIRED] . "[$name]", self::ERR_CODE_INPUT_REQUIRED);
                    }
                }

                //如果$arrInput数组存在该参数 对该参数进行格式校验
                if (isset($arrInput[$key]) && ($arrInput[$key] !== '')) {
                    self::ValidatorInputRow( $arrInput[$key],$arrRules, $key);
                }

            } catch (Exception $e) {
                $code = $e->getCode();
                $message = $e->getMessage();

                if ($GetMessage === false) {
                    throw new Exception($message, $code);
                }

                $errMessages[$key] = array(
                    'code'    => $code,
                    'message' => $message,
                );
            }
        }
        return $errMessages;
    }

    /**
     * ValidatorInputRow   @desc  单条验证
     * @param $rules
     *               array(
     *               'required',
     *               'type'=>'string',     enum[integer|number,string]
     *               'format'=>'date',
     *               'pattern'=>'#^1[3456789]\d{9}$#',
     *               'min'=>'1',
     *               'max'=>'2',
     *               'enum'=>array('1','2','3'),
     *               'nameCn'=>'中文名称',
     *               ),
     *               date-time    2016-09-18 12:12:12
     *               date     2016-09-18
     *               time     12:12:12
     *               utc-millisec     [>=0]
     *               ‘color’  ‘maroon’, ‘red’, ‘orange’, ‘yellow’, ‘olive’, ‘green’, ‘purple’, ‘fuchsia’, ‘lime’, ‘teal’, ‘aqua’, ‘blue’, ‘navy’, ‘black’, ‘gray’, ‘silver’, ‘white’  颜色值
     *               style
     *               phone
     * @param $value 验证的值
     * @param $name  字段名称
     * @throws Exception
     * @return bool
     */
    static public function ValidatorInputRow($value,$rules, $name) {
        $rules = self::ruleTransform($rules);
        $name = isset($rules['nameCn']) ? $rules['nameCn'] : $name;
        $typeRow = isset($rules['type']) ? $rules['type'] : 'string';



        if(isset($rules['required'])){
            self::checkFormat($value, 'required', $name);
            unset($rules['required']);
        }

        if(isset($rules['type'])){
            self::checkFormat($value, $typeRow, $name);
            unset($rules['type']);
        }

        foreach ($rules as $key => $val) {
            switch ($key) {
                case 'format':
                    self::checkFormat($value, $val, $name);
                    break;
                case 'pattern':
                    if (!preg_match($val, $value)) {
                        $msg = sprintf('参数 [%s] 与指定的规则不匹配', $name);
                        throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                    }
                    break;
                case 'min':
                    if (($typeRow === 'integer') || ($typeRow === 'int') || ($typeRow === 'number')) {
                        if (intval($value) < (intval($val))) {
                            $msg = sprintf('参数 [%s] 最小值为[%s]', $name, $val);
                            throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                        }
                    } else {
                        if (mb_strlen($value, 'UTF8') < ((int)$val)) {
                            $msg = sprintf('参数 [%s] 最小长度为[%s]', $name, $val);
                            throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                        }
                    }
                    break;
                case 'max':
                    if (($typeRow === 'integer') || ($typeRow === 'int') || ($typeRow === 'number')) {
                        if (intval($value) > (intval($val))) {
                            $msg = sprintf('参数 [%s] 最大值为[%s]', $name, $val);
                            throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                        }
                    } else {
                        if (mb_strlen($value, 'UTF8') > ((int)$val)) {
                            $msg = sprintf('参数 [%s] 最大长度为[%s]', $name, $val);
                            throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                        }
                    }
                    break;
                case 'enum':
                    if (!in_array($value, $val)) {
                        $msg = sprintf('参数 [%s] 不是有效的输入', $name);
                        throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                    }
                    break;
                default:
            }
        }
        return true;
    }


    /**
     * checkFormat   @desc  检测数值的数据类型
     * @param $value
     * @param $type
     * @param $valueName
     * @return bool
     * @throws Exception
     */
    public static function checkFormat($value, $type, $valueName = '') {
        $valid = true;
        switch ($type) {
            case 'string':
                if (is_string($value)) {
                    $xssEntity = self::xssValidator($value);
                    if ($xssEntity != $value) {
                        $msg = sprintf('[%s]对应的数值非法(存在跨站脚本攻击)', $valueName);
                        throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
                    }
                } else {
                    $valid = false;
                }
                break;
            case 'int':
            case 'integer':
                if ((!is_numeric($value)) || ($value != (int)$value)) {
                    $valid = false;
                }
                break;
            case 'number':
                if (!is_numeric($value)) {
                    $valid = false;
                }
                break;
            case 'phone':
                if (!preg_match('#^1[3456789]\d{9}$#', $value)) {
                    $valid = false;
                }
                break;
            case 'uri':
                if (!preg_match('#^[A-Za-z0-9:/;,\-_\?&\.%\+\|\#=]*$#', $value)) {
                    $valid = false;
                }
                break;
            case 'date-time':
                if (!preg_match('#^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}$#', $value)) {
                    $valid = false;
                }
                break;
            case 'date':
                if (!preg_match('#^\d{4}-\d{2}-\d{2}$#', $value)) {
                    $valid = false;
                }
                $type = 'xxxx-xx-xx';
                break;
            case 'time':
                if (!preg_match('#^\d{2}:\d{2}:\d{2}$#', $value)) {
                    $valid = false;
                }
                break;
            case 'utc-millisec':
                if ($value < 0) {
                    $valid = false;
                }
                break;
            case 'color':
                $arrColor = array(
                    'maroon',
                    'red',
                    'orange',
                    'yellow',
                    'olive',
                    'green',
                    'purple',
                    'fuchsia',
                    'lime',
                    'teal',
                    'aqua',
                    'blue',
                    'navy',
                    'black',
                    'gray',
                    'silver',
                    'white',
                );
                if (!in_array($value, $arrColor)) {
                    if (!preg_match('#^\#[0-9A-F]{6}$#', $value) && !preg_match('#^\#[0-9A-F]{3}$#', $value)) {
                        $valid = false;
                    }
                }
                break;
            case 'style':
                if (!preg_match('#(\.*?)[ ]?:[ ]?(.*?)#', $value)) {
                    $valid = false;
                }
                break;
            default:
                //调用自定义 Validator 类
                $functionName = "{$type}Validator";
                if(method_exists(__CLASS__,$functionName)){
                    $valid = self::$functionName($value);
                }else{
                    $valid = false;
                }
        }

        if (!$valid) {
            $msg = sprintf(' 无效数值 [%s] ,数值格式必须是: [%s]', $valueName, $type);
            throw new Exception($msg, self::ERR_CODE_INPUT_ERROR);
        }
        return $valid;
    }

    /**
     * ruleTransform   @desc 验证规则转换
     * 如果是字符串规则则转成数组规则
     * @param $rule
     * @return array
     */
    static public function ruleTransform($rule) {
        //字符串验证规则转成数组验证规则
        if (is_array($rule)) {
            $arrRules = $rule;
        } else {
            $arrRule = explode('|', $rule);
            $arrRules = array();
            foreach ($arrRule as $rul) {
                $arrRul = explode('=', $rul);
                if (count($arrRul) === 1) {
                    $arrRules[$arrRul[0]] = $arrRul[0];
                } else if (count($arrRul) === 2) {
                    if ($arrRul[0] === 'enum') {
                        $arrRules[$arrRul[0]] = explode(',', $arrRul[1]);
                    } else {
                        $arrRules[$arrRul[0]] = $arrRul[1];
                    }
                }
            }
        }
        return $arrRules;
    }

    /**
     * requiredValidator   @desc 不能为空验证
     * @param $attribute
     * @param bool $trim
     * @return bool
     */
    public static function requiredValidator($attribute, $trim = true) {
        if(is_array($attribute)){
            $res = empty($attribute)?false:true;
        }elseif(is_string($attribute)){
            $attribute = $trim?trim($attribute):$attribute;
            $res = ($attribute==='')?false:true;
        }else{
            $res = empty($attribute)?false:true;
        }
        return $res;
    }

    /**
     * stringValidator   @desc 字符串验证
     * @param $attribute
     * @param $is
     * @return bool
     */
    public static function alphanumericValidator($attribute, $is) {
        $pattern = "/^[a-zA-Z0-9]{" . $is . "}$/";

        return preg_match($pattern, $attribute) === 1;
    }

    /**
     * emailValidator   @desc 邮件验证
     * @param $attribute
     * @param bool $allowName
     * @return bool
     */
    public static function emailValidator($attribute, $allowName = false) {
        $pattern = "/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/";
        $fullPattern = "/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/";

        $valid = preg_match($pattern, $attribute) || $allowName && preg_match($fullPattern, $attribute);
        return $valid;
    }

    /**
     * speCharValidator   @desc 特殊字符验证
     * @param $attribute
     * @return bool
     */
    public static function speCharValidator($attribute) {
        $pattern = "/[`~!@#\$%\^&\*\(\)\+=\{\}':;\[\],\.<>|\x{FF01}\x{FFE5}\x{2026}\x{FF08}\x{FF09}\x{2014}\x{3010}\x{3011}\x{2018}\x{2019}\x{201C}\x{201D}\x{FF1A}\x{FF1B}\x{FF0C}\x{3002}\x{3001}\x{FF1F}\x{300A}\x{300B}]+/u";
        return preg_match($pattern, $attribute) === 1;
    }


    /**
     * companyPhoneValidator   @desc 验证固话
     * @param $companyPhone
     * @return bool
     * @throws Exception
     */
    public static function companyPhoneValidator($companyPhone) {
        $match_res = preg_match("/^\d{3,4}[|-]\d+$/", $companyPhone);
        if (!$match_res) {
            throw new Exception('固定电话格式错误', self::ERR_CODE_INPUT_ERROR);
        } else {
            return true;
        }
    }

    /**
     * mobilenumberValidator   @desc 验证手机号
     * @param $mobilenumber
     * @return bool
     */
    public static function mobileNumberValidator($mobilenumber) {
        $match_res = preg_match("/^1[34578]\d{9}$/", $mobilenumber);

        if (!$match_res) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * cardValidator   @desc 银行卡号
     * @param $cardNo
     * @return bool
     * @throws Exception
     */
    public static function cardValidator($cardNo) {
        $match_res = preg_match("/^\d{16,19}$/", $cardNo);
        if (!$match_res) {
            throw new Exception('银行卡号格式错误', self::ERR_CODE_INPUT_ERROR);
        } else {
            return true;
        }
    }

    /**
     * passwordValidator   @desc 密码复杂度验证
     * @param $passwd
     * @param null $prcid
     * @throws Exception
     */
    public static function passwordValidator($passwd, $prcid = null) {
        $match_res = preg_match("/^[0-9]{6}$/", $passwd);
        if (!$match_res) {
            throw new Exception('密码必须是6为数字', self::ERR_CODE_INPUT_ERROR);
        }

        $match_res = preg_match("/(\d)(\\1){2}/ie", $passwd);
        if ($match_res) {
            throw new Exception('密码不可以包含3个或以上相同的数字', self::ERR_CODE_INPUT_ERROR);
        }
        $arrVarPassWd = array('012', '123', '234', '345', '456', '567', '678', '789', '890');
        for ($i = 0; $i < 4; $i++) {
            $subpasswd = substr($passwd, $i, 3);
            if (strstr('0123456789', $subpasswd) !== false) {
                throw new Exception('密码不可以包含3个或以上连续的数字(例如123)', self::ERR_CODE_INPUT_ERROR);
            }
            if (strstr('9876543210', $subpasswd) !== false) {
                throw new Exception('密码不可以包含3个或以上连续的数字(例如123)', self::ERR_CODE_INPUT_ERROR);
            }
        }
        if ($prcid != null && strstr($prcid, $passwd) !== false) {
            throw new Exception('密码不可以是身份证号的一部分', self::ERR_CODE_INPUT_ERROR);
        }
    }

    /**
     * 图片上传验证
     * @param string $base64
     * @return boolean
     */
    public static function base64ImageValidator($base64Image) {
        if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64Image)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * xssValidator   @desc xss 过滤
     * @param $data
     * @param int $htmlentities
     * @return mixed|string
     */
    public static function xssValidator($data, $htmlentities = 0) {
        $htmlentities && $data = htmlentities($data, ENT_QUOTES, 'utf-8');

        // Fix &entity\n;
        $data = str_replace(array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $data);
        $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
        $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
        $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');

        // Remove any attribute starting with "on" or xmlns
        $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);

        // Remove javascript: and vbscript: protocols
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"\\\\]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"\\\\]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"\\\\]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);

        // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"\\\\]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"\\\\]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"\\\\]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);

        // Remove namespaced elements (we do not need them)
        $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);

        do {
            // Remove really unwanted tags
            $old_data = $data;
            $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
        } while ($old_data !== $data);

        // we are done...
        //$data = self::filter_remote_img_type($data, false);
        return $data;
    }


    /**
     * @param $strParam 过滤特殊字符
     * @return mixed
     */
    public static function replaceSpecialChar($strParam) {
        $regex = "/\/|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\_|\+|\{|\}|\:|\<|\>|\?|\[|\]|\,|\.|\/|\;|\'|\`|\-|\=|\\\|\|/";
        return preg_replace($regex, "", $strParam);
    }

    /**
     * sql 注入 字符串过滤
     * @param $strData
     * @return mixed
     */
    public static function injectCheckMysql($strData) {
        return preg_replace('(select|inert|update|delete|from|\'|\/\*|\*|\.\.\/|\.\/|UNION|into|load_file|outfile)', '', $strData);
    }


    /**
     * 检查Refer
     * @param string $method //方法名
     * @return boolean
     * @assert ( 'ajaxcomment' ) == true
     */
    public static function checkRefer($method = '') {
        $refConfig = Bd_Conf::getAppConf('referer');
        //判断checkref 是否开启状态
        if ($refConfig['checkRefererSwitch'] != 1) {
            return true;
        }
        //ref 为空 抛出异常
        if (empty($_SERVER['HTTP_REFERER'])) {
            throw new Exception(self::getMsg(self::ERR_CODE_CHECK_REFER), self::ERR_CODE_CHECK_REFER);
        }
        //获取conf 信息
        if (isset($refConfig['conf'][$method]) && count($refConfig['conf'][$method]) > 0) {
            $refList = $refConfig['conf'][$method];
        } elseif (isset($refConfig['conf']['default']) && count($refConfig['conf']['default']) > 0) {
            $refList = $refConfig['conf']['default'];
        } else {
            $refList = array();
        }

        //循环获取list
        if (!empty($refList)) {
            $ref = &$_SERVER['HTTP_REFERER'];
            if (strpos($ref, 'http://') !== 0 && strpos($ref, 'https://') !== 0) {
                $ref = 'http://' . $ref;
            }
            foreach ($refList as $item) {
                preg_match($item, $ref, $arrPregMatch);
                if (count($arrPregMatch) > 0) {
                    return true;
                }
            }
            //未匹配上正则 直接抛出异常
            throw new Exception(self::getMsg(self::ERR_CODE_CHECK_REFER), self::ERR_CODE_CHECK_REFER);
        }
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容