項(xiàng)目筆記/配置/jwt/isdangerous

前端文件開發(fā)預(yù)覽

可以使用前端node.js 提供的服務(wù)器live-server作為前端開發(fā)服務(wù)器使用。安裝node.js的版本控制工具nvm啃洋,在終端中執(zhí)行
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
重新進(jìn)入終端,使用nvm安裝最新版本的node.js
nvm install node
安裝live-server
npm install -g live-server
使用:在靜態(tài)文件目錄front_end_pc下執(zhí)行
live-server
live-server運(yùn)行在8080端口下掐暮,可以通過(guò)127.0.0.1:8080來(lái)訪問(wèn)靜態(tài)頁(yè)面芹助。

修改manage.py文件洪囤,在開發(fā)和生產(chǎn)環(huán)境中指定使用不同的配置:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "meiduo_mall.settings.dev")

為本項(xiàng)目創(chuàng)建數(shù)據(jù)庫(kù)用戶(不再使用root賬戶)
create user meiduo identified by 'meiduo';
grant all on meiduo_mall.* to 'meiduo'@'%';
flush privileges;
說(shuō)明:
第一句:創(chuàng)建用戶賬號(hào) meiduo, 密碼 meiduo (由identified by 指明)
第二句:授權(quán)meiduo_mall數(shù)據(jù)庫(kù)下的所有表(meiduo_mall.*)的所有權(quán)限(all)給用戶meiduo在以任何ip訪問(wèn)數(shù)據(jù)庫(kù)的時(shí)候('meiduo'@'%')
第三句:刷新生效用戶權(quán)限

根據(jù)配置文件路徑,來(lái)設(shè)置項(xiàng)目的工程路徑,便于導(dǎo)包
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))

添加導(dǎo)包路徑,將apps路徑添加進(jìn)去

import sys
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

在INSTALLED_APPS中添加rest_framework框架
INSTALLED_APPS = [
'rest_framework',
]

3. 數(shù)據(jù)庫(kù)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 數(shù)據(jù)庫(kù)主機(jī)
        'PORT': 3306,  # 數(shù)據(jù)庫(kù)端口
        'USER': 'name',  # 數(shù)據(jù)庫(kù)用戶名
        'PASSWORD': 'mima',  # 數(shù)據(jù)庫(kù)用戶密碼
        'NAME': 'database_name'  # 數(shù)據(jù)庫(kù)名字
    }
}

注意:在項(xiàng)目包init中添加mysql轉(zhuǎn)換操作:

import pymysql
pymysql.install_as_MySQLdb()

4. Redis

安裝django-redis跑慕,并配置

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://10.211.55.5:6379/0",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    "session": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://10.211.55.5:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"

除了名為default的redis配置外万皿,還補(bǔ)充了名為session的redis配置,分別使用兩個(gè)不同的redis庫(kù)相赁。同時(shí)修改了Django的Session機(jī)制使用redis保存相寇,且使用名為'session'的redis配置慰于。

關(guān)于django-redis 的使用钮科,說(shuō)明文檔可見http://django-redis-chs.readthedocs.io/zh_CN/latest/

5. 本地化語(yǔ)言與時(shí)區(qū)

LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'

6. 日志

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,  # 是否禁用已經(jīng)存在的日志器
    'formatters': {  # 日志信息顯示的格式
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {  # 對(duì)日志進(jìn)行過(guò)濾
        'require_debug_true': {  # django在debug模式下才輸出日志
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {  # 日志處理方法
        'console': {  # 向終端中輸出日志
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {  # 向文件中輸出日志
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/meiduo.log"),  # 日志文件的位置
            'maxBytes': 300 * 1024 * 1024,
            'backupCount': 10,
            'formatter': 'verbose'
        },
    },
    'loggers': {  # 日志器
        'django': {  # 定義了一個(gè)名為django的日志器
            'handlers': ['console', 'file'],  # 可以同時(shí)向終端與文件中輸出日志
            'propagate': True,  # 是否繼續(xù)傳遞日志信息
            'level': 'INFO',  # 日志器接收的最低日志級(jí)別
        },
    }
}

7. 異常處理

修改Django REST framework的默認(rèn)異常處理方法,補(bǔ)充處理數(shù)據(jù)庫(kù)異常和Redis異常婆赠。會(huì)抓取一般的鏈接數(shù)據(jù)庫(kù)的(查詢過(guò)程中斷開的)異常.但無(wú)法抓取具體的數(shù)據(jù)庫(kù)(查詢:不存在,插入:已存在)的異常新建utils/exceptions.py

from rest_framework.views import exception_handler as drf_exception_handler
import logging
from django.db import DatabaseError
from redis.exceptions import RedisError
from rest_framework.response import Response
from rest_framework import status
# 獲取在配置文件中定義的logger绵脯,用來(lái)記錄日志
logger = logging.getLogger('django')
def exception_handler(exc, context):
    """
    自定義異常處理
    :param exc: 異常
    :param context: 拋出異常的上下文
    :return: Response響應(yīng)對(duì)象
    """
    # 調(diào)用drf框架原生的異常處理方法
    response = drf_exception_handler(exc, context)
    if response is None:
        view = context['view']
        if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
            # 數(shù)據(jù)庫(kù)異常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': '服務(wù)器內(nèi)部錯(cuò)誤'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
    return response

配置文件中添加

REST_FRAMEWORK = {
    # 異常處理
    'EXCEPTION_HANDLER': 'meiduo_mall.utils.exceptions.exception_handler',
}

用戶模型類

Django提供了認(rèn)證系統(tǒng)佳励,文檔資料可參考此鏈接https://yiyibooks.cn/xx/Django_1.11.6/topics/auth/index.html

Django認(rèn)證系統(tǒng)同時(shí)處理認(rèn)證和授權(quán)。簡(jiǎn)單地講蛆挫,認(rèn)證驗(yàn)證一個(gè)用戶是否它們聲稱的那個(gè)人赃承,授權(quán)決定一個(gè)通過(guò)了認(rèn)證的用戶被允許做什么。 這里的詞語(yǔ)“認(rèn)證”同時(shí)指代這兩項(xiàng)任務(wù)悴侵,即Django的認(rèn)證系統(tǒng)同時(shí)提供了認(rèn)證機(jī)制和權(quán)限機(jī)制瞧剖。

Django的認(rèn)證系統(tǒng)包含:

  • 用戶
  • 權(quán)限:二元(是/否)標(biāo)志指示一個(gè)用戶是否可以做一個(gè)特定的任務(wù)。
  • 組:對(duì)多個(gè)用戶運(yùn)用標(biāo)簽和權(quán)限的一種通用的方式可免。
  • 一個(gè)可配置的密碼哈希系統(tǒng)
  • 用戶登錄或內(nèi)容顯示的表單和視圖
  • 一個(gè)可插拔的后臺(tái)系統(tǒng)

Django用戶模型類

Django認(rèn)證系統(tǒng)中提供了用戶模型類User保存用戶的數(shù)據(jù)抓于,默認(rèn)的User包含以下常見的基本字段:

  • username
    必選。 150個(gè)字符以內(nèi)浇借。 用戶名可能包含字母數(shù)字捉撮,_@妇垢,+ .-個(gè)字符巾遭。在Django更改1.10:max_length從30個(gè)字符增加到150個(gè)字符。
  • first_name
    可選(blank=True)闯估。 少于等于30個(gè)字符灼舍。
  • last_name
    可選(blank=True)。 少于等于30個(gè)字符涨薪。
  • email
    可選(blank=True)片仿。 郵箱地址。
  • password
    必選尤辱。 密碼的哈希及元數(shù)據(jù)砂豌。 (Django 不保存原始密碼)。 原始密碼可以無(wú)限長(zhǎng)而且可以包含任意字符光督。
  • groups
    Group 之間的多對(duì)多關(guān)系阳距。
  • user_permissions
    Permission 之間的多對(duì)多關(guān)系。
  • is_staff
    布爾值结借。 指示用戶是否可以訪問(wèn)Admin 站點(diǎn)筐摘。
  • is_active
    布爾值。 指示用戶的賬號(hào)是否激活船老。 我們建議您將此標(biāo)志設(shè)置為False而不是刪除帳戶咖熟;這樣,如果您的應(yīng)用程序?qū)τ脩粲腥魏瓮怄I柳畔,則外鍵不會(huì)中斷馍管。它不是用來(lái)控制用戶是否能夠登錄。 在Django更改1.10:在舊版本中薪韩,默認(rèn)is_active為False不能進(jìn)行登錄确沸。
  • is_superuser
    布爾值捌锭。 指定這個(gè)用戶擁有所有的權(quán)限而不需要給他們分配明確的權(quán)限。
  • last_login
    用戶最后一次登錄的時(shí)間罗捎。
  • date_joined
    賬戶創(chuàng)建的時(shí)間观谦。 當(dāng)賬號(hào)創(chuàng)建時(shí),默認(rèn)設(shè)置為當(dāng)前的date/time桨菜。
常用方法:
  • set_password(raw_password)
    設(shè)置用戶的密碼為給定的原始字符串豁状,并負(fù)責(zé)密碼的。 不會(huì)保存User 對(duì)象倒得。當(dāng)Noneraw_password 時(shí)替蔬,密碼將設(shè)置為一個(gè)不可用的密碼。
  • check_password(raw_password)
    如果給定的raw_password是用戶的真實(shí)密碼屎暇,則返回True承桥,可以在校驗(yàn)用戶密碼時(shí)使用。
管理器方法:

管理器方法即可以通過(guò)User.objects. 進(jìn)行調(diào)用的方法根悼。

  • create_user(username, email=None, password=None, **extra_fields)
    創(chuàng)建凶异、保存并返回一個(gè)User對(duì)象。
  • create_superuser(username, email, password, **extra_fields)
    create_user() 相同挤巡,但是設(shè)置is_staffis_superuserTrue剩彬。

創(chuàng)建自定義的用戶模型類

Django認(rèn)證系統(tǒng)中提供的用戶模型類及方法很方便,我們可以使用這個(gè)模型類矿卑,但是字段有些無(wú)法滿足項(xiàng)目需求喉恋,如本項(xiàng)目中需要保存用戶的手機(jī)號(hào),需要給模型類添加額外的字段母廷。
Django提供了django.contrib.auth.models.AbstractUser用戶抽象模型類允許我們繼承轻黑,擴(kuò)展字段來(lái)使用Django認(rèn)證系統(tǒng)的用戶模型類。

我們現(xiàn)在在meiduo/meiduo_mall/apps中創(chuàng)建Django應(yīng)用users琴昆,并在配置文件中注冊(cè)u(píng)sers應(yīng)用氓鄙。
在創(chuàng)建好的應(yīng)用models.py中定義用戶的用戶模型類。

class User(AbstractUser):
    """用戶模型類"""
    mobile = models.CharField(max_length=11, unique=True, verbose_name='手機(jī)號(hào)')
    class Meta:
        db_table = 'tb_users'
        verbose_name = '用戶'
        verbose_name_plural = verbose_name

我們自定義的用戶模型類還不能直接被Django的認(rèn)證系統(tǒng)所識(shí)別业舍,需要在配置文件中告知Django認(rèn)證系統(tǒng)使用我們自定義的模型類抖拦。
在配置文件中進(jìn)行設(shè)置

AUTH_USER_MODEL = 'users.User'

AUTH_USER_MODEL 參數(shù)的設(shè)置以點(diǎn).來(lái)分隔,表示應(yīng)用名.模型類名舷暮。
注意:Django建議我們對(duì)于AUTH_USER_MODEL參數(shù)的設(shè)置一定要在第一次數(shù)據(jù)庫(kù)遷移之前就設(shè)置好态罪,否則后續(xù)使用可能出現(xiàn)未知錯(cuò)誤。

執(zhí)行數(shù)據(jù)庫(kù)遷移

python manage.py makemigrations
python manage.py migrate

跨域CORS

我們?yōu)榍岸撕秃蠖朔謩e設(shè)置了兩個(gè)不同的域名
現(xiàn)在下面,前端與后端分處不同的域名复颈,我們需要為后端添加跨域訪問(wèn)的支持。
我們使用CORS來(lái)解決后端對(duì)跨域訪問(wèn)的支持诸狭。
使用django-cors-headers擴(kuò)展
參考文檔https://github.com/ottoyiu/django-cors-headers/

安裝

pip install django-cors-headers

添加應(yīng)用

INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

中間層設(shè)置

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ...
]

添加白名單

# CORS
CORS_ORIGIN_WHITELIST = (
    '127.0.0.1:8080',
    'localhost:8080',
 ........
)
CORS_ALLOW_CREDENTIALS = True  # 允許攜帶cookie
  • 凡是出現(xiàn)在白名單中的域名券膀,都可以訪問(wèn)后端接口
  • CORS_ALLOW_CREDENTIALS 指明在跨域訪問(wèn)中君纫,后端是否支持對(duì)cookie的操作驯遇。

Celery使用

項(xiàng)目目錄下創(chuàng)建celery_tasks用于保存celery異步任務(wù)芹彬。
在celery_tasks目錄下創(chuàng)建config.py文件,用于保存celery的配置信息
broker_url = "redis://127.0.0.1/14"
在celery_tasks目錄下創(chuàng)建main.py文件叉庐,用于作為celery的啟動(dòng)文件
from celery import Celery

為celery使用django配置文件進(jìn)行設(shè)置

import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo_mall.settings.dev'

創(chuàng)建celery應(yīng)用

app = Celery('異步任務(wù)名')

導(dǎo)入celery配置

app.config_from_object('celery_tasks.config')

自動(dòng)注冊(cè)celery任務(wù)

app.autodiscover_tasks(['celery_tasks.sms'])
在celery_tasks目錄下創(chuàng)建sms目錄舒帮,用于放置發(fā)送短信的異步任務(wù)相關(guān)代碼。
將提供的發(fā)送短信的云通訊SDK放到celery_tasks/sms/目錄下陡叠。
在celery_tasks/sms/目錄下創(chuàng)建tasks.py文件玩郊,用于保存發(fā)送短信的異步任務(wù)
import logging
from celery_tasks.main import app
from .yuntongxun.sms import CCP
logger = logging.getLogger("django")

驗(yàn)證碼短信模板

SMS_CODE_TEMP_ID = 1
@app.task(name='send_sms_code')
def send_sms_code(mobile, code, expires):
"""
發(fā)送短信驗(yàn)證碼
:param mobile: 手機(jī)號(hào)
:param code: 驗(yàn)證碼
:param expires: 有效期
:return: None
"""
try:
ccp = CCP()
result = ccp.send_template_sms(mobile, [code, expires], SMS_CODE_TEMP_ID)
except Exception as e:
logger.error("發(fā)送驗(yàn)證碼短信[異常][ mobile: %s, message: %s ]" % (mobile, e))
else:
if result == 0:
logger.info("發(fā)送驗(yàn)證碼短信[正常][ mobile: %s ]" % mobile)
else:
logger.warning("發(fā)送驗(yàn)證碼短信[失敗][ mobile: %s ]" % mobile)
在需要發(fā)送短信的視圖中,使用celery異步任務(wù)發(fā)送短信
from celery_tasks.sms import tasks as sms_tasks
class SMSCodeView(GenericAPIView):
# 發(fā)送短信驗(yàn)證碼,使用delay將任務(wù)加入到異步隊(duì)列
sms_tasks.send_sms_code.delay(mobile, sms_code, sms_code_expires)

JWT

JWT的構(gòu)成
第一部分我們稱它為頭部(header),第二部分我們稱其為載荷(payload, 類似于飛機(jī)上承載的物品)枉阵,第三部分是簽證(signature).

注意:secret是保存在服務(wù)器端的译红,jwt的簽發(fā)生成也是在服務(wù)器端的,secret就是用來(lái)進(jìn)行jwt的簽發(fā)和jwt的驗(yàn)證兴溜,所以侦厚,它就是你服務(wù)端的私鑰,在任何場(chǎng)景都不應(yīng)該流露出去拙徽。一旦客戶端得知這個(gè)secret, 那就意味著客戶端是可以自我簽發(fā)jwt了刨沦。

Django REST framework JWT

我們?cè)隍?yàn)證完用戶的身份后(檢驗(yàn)用戶名和密碼),需要向用戶簽發(fā)JWT膘怕,在需要用到用戶身份信息的時(shí)候想诅,還需核驗(yàn)用戶的JWT。
關(guān)于簽發(fā)和核驗(yàn)JWT岛心,我們可以使用Django REST framework JWT擴(kuò)展來(lái)完成来破。
文檔網(wǎng)站http://getblimp.github.io/django-rest-framework-jwt/

安裝配置

安裝

pip install djangorestframework-jwt

配置

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}
JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
  • JWT_EXPIRATION_DELTA 指明token的有效期

使用

Django REST framework JWT 擴(kuò)展的說(shuō)明文檔中提供了手動(dòng)簽發(fā)JWT的方法

from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)

前端保存token
我們可以將JWT保存在cookie中,也可以保存在瀏覽器的本地存儲(chǔ)里忘古,我們保存在瀏覽器本地存儲(chǔ)中
瀏覽器的本地存儲(chǔ)提供了sessionStorage 和 localStorage 兩種:
sessionStorage 瀏覽器關(guān)閉即失效
localStorage 長(zhǎng)期有效

  1. 后端實(shí)現(xiàn)
    Django REST framework JWT提供了登錄簽發(fā)JWT的視圖讳癌,可以直接使用
    from rest_framework_jwt.views import obtain_jwt_token
    urlpatterns = [
    url(r'^authorizations/$', obtain_jwt_token),
    ]
    但是默認(rèn)的返回值僅有token,我們還需在返回值中增加username和user_id存皂。
    通過(guò)修改該視圖的返回值可以完成我們的需求晌坤。
    在users/utils.py 中,創(chuàng)建
    def jwt_response_payload_handler(token, user=None, request=None):
    """
    自定義jwt認(rèn)證成功返回?cái)?shù)據(jù)
    """
    return {
    'token': token,
    'user_id': user.id,
    'username': user.username
    }
    修改配置文件

JWT

JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',
}

  1. 增加支持用戶名與手機(jī)號(hào)均可作為登錄賬號(hào)
    JWT擴(kuò)展的登錄視圖旦袋,在收到用戶名與密碼時(shí)骤菠,也是調(diào)用Django的認(rèn)證系統(tǒng)中提供的authenticate()來(lái)檢查用戶名與密碼是否正確。
    我們可以通過(guò)修改Django認(rèn)證系統(tǒng)的認(rèn)證后端(主要是authenticate方法)來(lái)支持登錄賬號(hào)既可以是用戶名也可以是手機(jī)號(hào)疤孕。修改Django認(rèn)證系統(tǒng)的認(rèn)證后端需要繼承django.contrib.auth.backends.ModelBackend商乎,并重寫authenticate方法。
    authenticate(self, request, username=None, password=None, **kwargs)方法的參數(shù)說(shuō)明:
    request 本次認(rèn)證的請(qǐng)求對(duì)象
    username 本次認(rèn)證提供的用戶賬號(hào)
    password 本次認(rèn)證提供的密碼
    我們想要讓用戶既可以以用戶名登錄祭阀,也可以以手機(jī)號(hào)登錄鹉戚,那么對(duì)于authenticate方法而言鲜戒,username參數(shù)即表示用戶名或者手機(jī)號(hào)。

重寫authenticate方法的思路:
根據(jù)username參數(shù)查找用戶User對(duì)象抹凳,username參數(shù)可能是用戶名遏餐,也可能是手機(jī)號(hào)
若查找到User對(duì)象,調(diào)用User對(duì)象的check_password方法檢查密碼是否正確
在users/utils.py中編寫:
def get_user_by_account(account):
"""
根據(jù)帳號(hào)獲取user對(duì)象
:param account: 賬號(hào)赢底,可以是用戶名失都,也可以是手機(jī)號(hào)
:return: User對(duì)象 或者 None
"""
try:
if re.match('^1[3-9]\d{9}$', account):
# 帳號(hào)為手機(jī)號(hào)
user = User.objects.get(mobile=account)
else:
# 帳號(hào)為用戶名
user = User.objects.get(username=account)
except User.DoesNotExist:
return None
else:
return user

class UsernameMobileAuthBackend(ModelBackend):
"""
自定義用戶名或手機(jī)號(hào)認(rèn)證
"""
def authenticate(self, request, username=None, password=None, **kwargs):
user = get_user_by_account(username)
if user is not None and user.check_password(password):
return user

在配置文件中告知Django使用我們自定義的認(rèn)證后端
AUTHENTICATION_BACKENDS = [
'users.utils.UsernameMobileAuthBackend',
]

使用itsdangerous生成憑據(jù)access_token

itsdangerous模塊的參考資料連接http://itsdangerous.readthedocs.io/en/latest/

安裝
pip install itsdangerous
TimedJSONWebSignatureSerializer的使用

使用TimedJSONWebSignatureSerializer可以生成帶有有效期的token

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from django.conf import settings
# serializer = Serializer(秘鑰, 有效期秒)
serializer = Serializer(settings.SECRET_KEY, 300)
# serializer.dumps(數(shù)據(jù)), 返回bytes類型
token = serializer.dumps({'mobile': '18512345678'})
token = token.decode()

# 檢驗(yàn)token
# 驗(yàn)證失敗,會(huì)拋出itsdangerous.BadData異常
serializer = Serializer(settings.SECRET_KEY, 300)
try:
    data = serializer.loads(token)
except BadData:
    return None
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末幸冻,一起剝皮案震驚了整個(gè)濱河市粹庞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洽损,老刑警劉巖庞溜,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異碑定,居然都是意外死亡流码,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門不傅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)旅掂,“玉大人,你說(shuō)我怎么就攤上這事访娶∩膛埃” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵崖疤,是天一觀的道長(zhǎng)秘车。 經(jīng)常有香客問(wèn)我,道長(zhǎng)劫哼,這世上最難降的妖魔是什么叮趴? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮权烧,結(jié)果婚禮上眯亦,老公的妹妹穿的比我還像新娘。我一直安慰自己般码,他們只是感情好妻率,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著板祝,像睡著了一般宫静。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天孤里,我揣著相機(jī)與錄音伏伯,去河邊找鬼。 笑死捌袜,一個(gè)胖子當(dāng)著我的面吹牛说搅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播琢蛤,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼蜓堕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼抛虏!你這毒婦竟也來(lái)了博其?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤迂猴,失蹤者是張志新(化名)和其女友劉穎慕淡,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沸毁,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡峰髓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了息尺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片携兵。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖搂誉,靈堂內(nèi)的尸體忽然破棺而出徐紧,到底是詐尸還是另有隱情,我是刑警寧澤炭懊,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布并级,位于F島的核電站,受9級(jí)特大地震影響侮腹,放射性物質(zhì)發(fā)生泄漏嘲碧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一父阻、第九天 我趴在偏房一處隱蔽的房頂上張望愈涩。 院中可真熱鬧,春花似錦加矛、人聲如沸履婉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谐鼎。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狸棍,已是汗流浹背身害。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留草戈,地道東北人塌鸯。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像唐片,于是被迫代替她去往敵國(guó)和親丙猬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容