使用Java和Spring Security的JWT的REST安全性(譯)

一俐筋、安全

安全是方便的敵人儿礼,反之亦然。對(duì)于虛擬或真實(shí)的系統(tǒng),從物理入口到網(wǎng)絡(luò)銀行平臺(tái)榕堰,這一說法是真實(shí)的氓润。工程師不斷嘗試為給定的用例找到適當(dāng)?shù)钠胶忤档郏瑑A斜到一邊或另一側(cè)叔锐。

通常,當(dāng)出現(xiàn)新的威脅時(shí)紧帕,我們轉(zhuǎn)向安全盔然,遠(yuǎn)離方便。然后是嗜,我們看看是否可以恢復(fù)一些丟失的方便愈案,而不會(huì)降低安全性。此外鹅搪,這個(gè)惡性循環(huán)也永遠(yuǎn)存在站绪。

安全性與方便性

安全是方便的敵人,反之亦然涩嚣。

讓我們來看看REST服務(wù)目前在安全性和便利性方面的地位崇众。REST(代表代理狀態(tài)轉(zhuǎn)移)服務(wù)作為極其簡(jiǎn)化的Web服務(wù)開始掂僵,具有巨大的規(guī)范和繁瑣的格式航厚,例如:用于描述服務(wù)的 <u>WSDL</u> 或用于指定消息格式的 <u>SOAP</u>顷歌。在 REST 中,我們沒有一個(gè)幔睬。我們可以在純文本文件中描述 REST 服務(wù)眯漩,并使用我們想要的任何消息格式,如 JSON麻顶,XML赦抖,甚至是純文本。簡(jiǎn)化的方法也適用于 REST 服務(wù)的安全性; 沒有定義的標(biāo)準(zhǔn)強(qiáng)加了一種特定的方式來驗(yàn)證用戶辅肾。

雖然REST服務(wù)沒有太多的規(guī)定队萤,但重要的是缺少狀態(tài)。這意味著服務(wù)器不保留任何客戶端狀態(tài)矫钓,會(huì)話是一個(gè)很好的例子要尔。因此,服務(wù)器回復(fù)每個(gè)請(qǐng)求新娜,就好像它是客戶端的第一個(gè)赵辕。然而,即使現(xiàn)在概龄,許多實(shí)現(xiàn)仍然使用基于 cookie 的身份驗(yàn)證还惠,這是從標(biāo)準(zhǔn)網(wǎng)站架構(gòu)設(shè)計(jì)繼承的。REST 的無(wú)狀態(tài)方法使得會(huì)話 cookie 從安全的角度來看是不合適的私杜,但是它們?nèi)匀槐粡V泛使用蚕键。除了忽視所需的無(wú)國(guó)籍之外,簡(jiǎn)化的做法也是預(yù)期的安全性權(quán)衡衰粹。與用于 Web 服務(wù)的 WS-Security 標(biāo)準(zhǔn)相比锣光,創(chuàng)建和使用 REST 服務(wù)要容易得多,因此方便通過了屋頂寄猩。權(quán)衡是非常苗條的安全;

在嘗試從服務(wù)器中刪除客戶端會(huì)話時(shí)嫉晶,有些其他方法已經(jīng)被偶爾使用,比如 Basic 或 Digest HTTP 認(rèn)證田篇。兩者都使用一個(gè) Authorization 標(biāo)頭來傳送用戶憑證替废,并添加一些編碼(HTTP Basic)或加密(HTTP Digest)。當(dāng)然泊柬,它們?cè)诰W(wǎng)站上也出現(xiàn)了同樣的缺陷:HTTP Basic 必須通過 HTTPS 使用椎镣,因?yàn)橛脩裘兔艽a以易于逆轉(zhuǎn)的 base64 編碼發(fā)送,而 HTTP 摘要強(qiáng)制使用被證明是不安全的過時(shí)的 MD5 哈希值兽赁。

最后状答,一些實(shí)現(xiàn)使用任意令牌來驗(yàn)證客戶端冷守。這個(gè)選項(xiàng)似乎是我們現(xiàn)在最好的。如果正確實(shí)現(xiàn)惊科,它會(huì)修復(fù) HTTP Basic拍摇,HTTP Digest 或會(huì)話 cookie 的所有安全問題,使用起來很簡(jiǎn)單馆截,并且遵循無(wú)狀態(tài)模式充活。

然而,使用這種任意令牌蜡娶,所涉及的標(biāo)準(zhǔn)很少混卵。每個(gè)服務(wù)提供商都有他或她的想法放在令牌中,以及如何編碼或加密它窖张。來自不同提供商的消費(fèi)服務(wù)需要額外的設(shè)置時(shí)間幕随,只是為了適應(yīng)所使用的特定令牌格式。另一方面宿接,其他方法(會(huì)話 cookie赘淮,HTTP Basic 和 HTTP 摘要)是開發(fā)人員所熟知的,幾乎所有設(shè)備上的所有瀏覽器都可以開箱即用澄阳∮抵框架和語(yǔ)言已經(jīng)準(zhǔn)備好了這些方法,內(nèi)置函數(shù)可以無(wú)縫地處理碎赢。

二低剔、JWT

JWT(從 JSON Web Token 縮寫)是通常使用令牌進(jìn)行身份驗(yàn)證的缺少的標(biāo)準(zhǔn)化,不僅適用于 REST 服務(wù)肮塞。目前襟齿,草案狀態(tài)為 <u>RFC 7519</u>。它是強(qiáng)大的枕赵,可以攜帶大量的信息猜欺,但即使它的尺寸相對(duì)較小,仍然使用起來很簡(jiǎn)單拷窜。像任何其他令牌一樣开皿,JWT 可以用于在身份提供商和服務(wù)提供商(不一定是相同的系統(tǒng))之間傳遞身份驗(yàn)證的用戶身份。它還可以承載用戶的所有權(quán)利篮昧,例如授權(quán)數(shù)據(jù)赋荆,因此服務(wù)提供商不需要進(jìn)入數(shù)據(jù)庫(kù)或外部系統(tǒng)來驗(yàn)證每個(gè)請(qǐng)求的用戶角色和權(quán)限; 從令牌中提取數(shù)據(jù)。

以下是JWT的工作原理:

JWT流
  • 客戶端通過將其憑據(jù)發(fā)送給身份提供者來登錄懊昨。

  • 身份提供者驗(yàn)證憑據(jù); 如果一切正常窄潭,它將檢索用戶數(shù)據(jù),生成包含用于訪問服務(wù)的用戶詳細(xì)信息和權(quán)限的 JWT酵颁,并且還會(huì)在 JWT 上設(shè)置到期(可能是無(wú)限制的)嫉你。

  • 身份提供商簽名月帝,如果需要,加密 JWT幽污,并將其發(fā)送給客戶端嚷辅,作為對(duì)具有憑據(jù)的初始請(qǐng)求的響應(yīng)。

  • 客戶端根據(jù)身份提供商設(shè)置的到期時(shí)間限制或無(wú)限制地存儲(chǔ) JWT油挥。

  • 客戶端將所存儲(chǔ)的 JWT 發(fā)送到服務(wù)提供商的每個(gè)請(qǐng)求的授權(quán)頭中潦蝇。

  • 對(duì)于每個(gè)請(qǐng)求款熬,服務(wù)提供者從 Authorization 頭部接收 JWT 深寥,如果需要,對(duì)其進(jìn)行解密贤牛,驗(yàn)證簽名惋鹅,如果一切正常,則提取用戶數(shù)據(jù)和權(quán)限殉簸。僅基于這些數(shù)據(jù)闰集,并且再次查找數(shù)據(jù)庫(kù)中的進(jìn)一步細(xì)節(jié)或聯(lián)系身份提供者時(shí),它可以接受或拒絕客戶端請(qǐng)求般卑。唯一的要求是身份和服務(wù)提供商就加密達(dá)成協(xié)議武鲁,以便服務(wù)可以驗(yàn)證簽名,甚至解密哪個(gè)身份被加密蝠检。

這個(gè)流程允許很大的靈活性沐鼠,同時(shí)保持安全和容易開發(fā)。通過使用這種方法叹谁,可以輕松地向服務(wù)提供商集群添加新的服務(wù)器節(jié)點(diǎn)饲梭,只需要通過向其提供一個(gè)共享的秘密密鑰來初始化它們,只能驗(yàn)證簽名并解密令牌焰檩。不需要會(huì)話復(fù)制憔涉,數(shù)據(jù)庫(kù)同步或節(jié)點(diǎn)間通信。REST 在其充分的榮耀析苫。

JWT 和其他任意令牌之間的主要區(qū)別是令牌內(nèi)容的標(biāo)準(zhǔn)化兜叨。另一個(gè)推薦的方法是 Authorization 使用承載方案將 JWT 令牌發(fā)送到頭部。標(biāo)題的內(nèi)容應(yīng)如下所示:

Authorization: Bearer <token>

三衩侥、實(shí)施

對(duì)于 REST 服務(wù)国旷,如預(yù)期的那樣工作,與傳統(tǒng)的多頁(yè)面網(wǎng)站相比顿乒,我們需要稍微不同的授權(quán)方法议街。

當(dāng)客戶端請(qǐng)求安全資源時(shí),REST 服務(wù)器不會(huì)通過重定向到登錄頁(yè)面來觸發(fā)身份驗(yàn)證過程璧榄,因此 REST 服務(wù)器使用請(qǐng)求本身可用的數(shù)據(jù)(在這種情況下為 JWT 令牌)來認(rèn)證所有請(qǐng)求特漩。如果這樣的認(rèn)證失敗吧雹,重定向就沒有意義了。REST API 只是發(fā)送 HTTP 代碼 401(未經(jīng)授權(quán))的響應(yīng)涂身,客戶端應(yīng)該知道該怎么做; 例如雄卷,瀏覽器將顯示動(dòng)態(tài) div,以允許用戶提供用戶名和密碼蛤售。

另一方面丁鹉,在經(jīng)典的多頁(yè)面網(wǎng)站中成功的認(rèn)證之后,用戶通過使用HTTP代碼 301(永久移動(dòng))來重定向悴能,通常到主頁(yè)揣钦,或者甚至更好地到達(dá)用戶最初請(qǐng)求觸發(fā)的頁(yè)面認(rèn)證過程。使用 REST漠酿,這再?zèng)]有任何意義冯凹。相反,我們將繼續(xù)執(zhí)行請(qǐng)求炒嘲,就像資源根本不安全一樣宇姚,返回 HTTP 代碼 200(OK)和預(yù)期的響應(yīng)體。

四夫凸、Spring Security

REST安全與JWT浑劳,Spring安全和Java

現(xiàn)在,我們來看看如何使用 <u>Java</u> 和 <u>Spring</u> 來 <u>實(shí)現(xiàn)</u> 基于JWT 令牌的 REST API夭拌,同時(shí)嘗試重用 Spring 安全性默認(rèn)行為魔熏。正如預(yù)期的那樣,Spring Security 框架帶有許多準(zhǔn)備插入的類啼止,它們處理“舊”授權(quán)機(jī)制:會(huì)話 cookie道逗,HTTP Basic 和 HTTP 摘要。然而献烦,它缺乏對(duì) JWT 的本地支持滓窍,我們需要自己動(dòng)手,使其工作巩那。

首先吏夯,我們從普通的Spring Security過濾器定義開始 web.xml

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

請(qǐng)注意,過濾器的名稱必須恰好 springSecurityFilterChain 適用于Spring配置的其余部分才能開箱即用即横。

接下來是與安全性相關(guān)的 Spring bean 的 XML 聲明噪生。為了簡(jiǎn)化 XML,我們將 security 通過添加 xmlns="http://www.springframework.org/schema/security" 到根 XML 元素來設(shè)置默認(rèn)命名空間东囚。

其余的XML如下所示:

<global-method-security pre-post-annotations="enabled" /> (1)

<http pattern="/api/login" security="none"/> (2)
<http pattern="/api/signup" security="none"/>

<http pattern="/api/**" entry-point-ref="restAuthenticationEntryPoint" create-session="stateless"> (3)
    <csrf disabled="true"/> (4) 
    <custom-filter before="FORM_LOGIN_FILTER" ref="jwtAuthenticationFilter"/> (5) 
</http> 

<beans:bean id="jwtAuthenticationFilter" class="com.toptal.travelplanner.security.JwtAuthenticationFilter"> (6) 
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="authenticationSuccessHandler" ref="jwtAuthenticationSuccessHandler" /> (7)
 </beans:bean>

<authentication-manager alias="authenticationManager"> 
    <authentication-provider ref="jwtAuthenticationProvider" /> (8) 
</authentication-manager>
  • (1)在這一行中跺嗽,我們激活 @PreFilter@PreAuthorize@PostFilter桨嫁,@PostAuthorize 在上下文任何彈簧豆注釋植兰。

  • (2)我們定義登錄和注冊(cè)端點(diǎn)來跳過安全性; 甚至“匿名”都應(yīng)該能夠做這兩個(gè)操作。

  • (3)接下來璃吧,我們定義應(yīng)用于所有請(qǐng)求的過濾器鏈楣导,同時(shí)添加兩個(gè)重要的配置:入口點(diǎn)引用和設(shè)置會(huì)話創(chuàng)建 stateless(我們不希望為安全起見創(chuàng)建會(huì)話,因?yàn)槲覀冋跒槊總€(gè)請(qǐng)求使用令牌)畜挨。

  • (4)我們不需要 csrf 保護(hù)筒繁,因?yàn)槲覀兊牧钆剖敲庖叩摹?/p>

  • (5)接下來,我們?cè)?Spring 的預(yù)定義過濾器鏈中插入特殊的認(rèn)證過濾器巴元,就在 Form 登錄過濾器之前毡咏。

  • (6)這個(gè) bean 是我們認(rèn)證過濾器的聲明; 因?yàn)樗菙U(kuò)展Spring的 AbstractAuthenticationProcessingFilter,我們需要用XML聲明它的屬性(自動(dòng)電線在這里不工作)务冕。我們稍后會(huì)介紹過濾器的功能血当。

  • (7)默認(rèn)的成功處理程序 AbstractAuthenticationProcessingFilter 不足以用于 REST,因?yàn)樗鼘⒂脩糁囟ㄏ虻匠晒?yè)面; 這就是為什么我們自己設(shè)在這里禀忆。

  • (8)authenticationManager 由我們的過濾器使用的提供者創(chuàng)建的聲明對(duì)用戶進(jìn)行身份驗(yàn)證。

現(xiàn)在來看看我們?nèi)绾螌?shí)現(xiàn)在上面的 XML 中聲明的特定類落恼。請(qǐng)注意箩退,Spring 將為我們接線。我們從最簡(jiǎn)單的開始佳谦。

RestAuthenticationEntryPoint.java

public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
        // This is invoked when user tries to access a secured REST resource without supplying any credentials
        // We should just send a 401 Unauthorized response because there is no 'login page' to redirect to
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }
}

如上所述戴涝,當(dāng)驗(yàn)證失敗時(shí),該類只返回 HTTP 代碼 401(未授權(quán))钻蔑,覆蓋默認(rèn)的 Spring 的重定向啥刻。

JwtAuthenticationSuccessHandler.java

public class JwtAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        // We do not need to do anything extra on REST authentication success, because there is no page to redirect to
    }

}

此簡(jiǎn)單的覆蓋將刪除成功身份驗(yàn)證的默認(rèn)行為(重定向到家庭或用戶請(qǐng)求的任何其他頁(yè)面)。如果您想知道為什么我們不需要覆蓋它 AuthenticationFailureHandler咪笑,那是因?yàn)槿绻丛O(shè)置重定向網(wǎng)址可帽,則默認(rèn)實(shí)現(xiàn)不會(huì)重定向到任何位置,所以我們只是避免設(shè)置 URL窗怒。

JwtAuthenticationFilter.java

public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public JwtAuthenticationFilter() {
        super("/**");
    }

    @Override
    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        return true;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        String header = request.getHeader("Authorization");

        if (header == null || !header.startsWith("Bearer ")) {
            throw new JwtTokenMissingException("No JWT token found in request headers");
        }

        String authToken = header.substring(7);

        JwtAuthenticationToken authRequest = new JwtAuthenticationToken(authToken);

        return getAuthenticationManager().authenticate(authRequest);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, authResult);

        // As this authentication is in HTTP header, after success we need to continue the request normally
        // and return the response as if the resource was not secured at all
        chain.doFilter(request, response);
    }
}

這個(gè)類是 JWT 身份驗(yàn)證過程的切入點(diǎn)映跟。該過濾器從請(qǐng)求頭提取JWT令牌,并將認(rèn)證委托給注入 AuthenticationManager扬虚。如果未找到令牌努隙,將拋出異常,停止處理請(qǐng)求辜昵。我們還需要覆蓋成功的認(rèn)證荸镊,因?yàn)槟J(rèn)的 Spring 流將停止過濾器鏈并繼續(xù)執(zhí)行重定向。請(qǐng)記住,我們需要鏈條完全執(zhí)行躬存,包括生成響應(yīng)收厨,如上所述。

JwtAuthenticationProvider.java

public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public boolean supports(Class<?> authentication) {
        return (JwtAuthenticationToken.class.isAssignableFrom(authentication));
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    }

    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication;
        String token = jwtAuthenticationToken.getToken();

        User parsedUser = jwtUtil.parseToken(token);

        if (parsedUser == null) {
            throw new JwtTokenMalformedException("JWT token is not valid");
        }

        List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(parsedUser.getRole());

        return new AuthenticatedUser(parsedUser.getId(), parsedUser.getUsername(), token, authorityList);
    }

}

在這個(gè)類中优构,我們使用 Spring 的默認(rèn)值 AuthenticationManager诵叁,但是我們注入自己 AuthenticationProvider 的實(shí)際身份驗(yàn)證過程。為了實(shí)現(xiàn)這一點(diǎn)钦椭,我們擴(kuò)展了它 AbstractUserDetailsAuthenticationProvider拧额,它要求我們僅 UserDetails 基于身份驗(yàn)證請(qǐng)求返回,在我們的例子中彪腔,包含在 JwtAuthenticationToken 類中的 JWT 令牌侥锦。如果令牌無(wú)效,我們拋出異常德挣。然而恭垦,如果它是有效的并且解密 JwtUtil 成功,我們將提取用戶的詳細(xì)信息(我們將在 JwtUtil 課堂上看到如何)格嗅,而不需要訪問數(shù)據(jù)庫(kù)番挺。關(guān)于用戶的所有信息(包括他或她的角色)都包含在令牌本身中。

JwtUtil.java

public class JwtUtil {

    @Value("${jwt.secret}")
    private String secret;

    /**
     * Tries to parse specified String as a JWT token. If successful, returns User object with username, id and role prefilled (extracted from token).
     * If unsuccessful (token is invalid or not containing all required user properties), simply returns null.
     * 
     * @param token the JWT token to parse
     * @return the User object extracted from specified token or null if a token is invalid.
     */
    public User parseToken(String token) {
        try {
            Claims body = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();

            User u = new User();
            u.setUsername(body.getSubject());
            u.setId(Long.parseLong((String) body.get("userId")));
            u.setRole((String) body.get("role"));

            return u;

        } catch (JwtException | ClassCastException e) {
            return null;
        }
    }

    /**
     * Generates a JWT token containing username as subject, and userId and role as additional claims. These properties are taken from the specified
     * User object. Tokens validity is infinite.
     * 
     * @param u the user for which the token will be generated
     * @return the JWT token
     */
    public String generateToken(User u) {
        Claims claims = Jwts.claims().setSubject(u.getUsername());
        claims.put("userId", u.getId() + "");
        claims.put("role", u.getRole());

        return Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
}

最后屯掖, JwtUtil 類負(fù)責(zé)將令牌解析為 User 對(duì)象玄柏,并從 User 對(duì)象生成令牌。它是直接的贴铜,因?yàn)樗褂?<u>jjwt圖書館</u> 來完成所有的 JWT 工作粪摘。在我們的例子中,我們簡(jiǎn)單地將用戶名绍坝,用戶ID和用戶角色存儲(chǔ)在令牌中徘意。我們還可以存儲(chǔ)更多的任意東西,并添加更多的安全功能轩褐,例如令牌的到期椎咧。 AuthenticationProvider 如上所示,使用令牌的解析灾挨。該 generateToken() 方法從登錄和注冊(cè) REST 服務(wù)調(diào)用邑退,它們是不安全的,并且不會(huì)觸發(fā)任何安全檢查或要求令牌存在于請(qǐng)求中劳澄。最后地技,它會(huì)根據(jù)用戶生成將返回給客戶端的令牌。

五秒拔、結(jié)論

雖然舊的標(biāo)準(zhǔn)化安全方法(會(huì)話 cookie莫矗,HTTP Basic 和 HTTP 摘要)也可以與 REST 服務(wù)一起使用,但是它們都有一些問題,通過使用更好的標(biāo)準(zhǔn)來避免這種情況作谚。JWT 即將到來三娩,以節(jié)省時(shí)間,最重要的是非常接近成為 IETF 標(biāo)準(zhǔn)妹懒。

JWT 的主要優(yōu)勢(shì)是在無(wú)狀態(tài)的情況下處理用戶身份驗(yàn)證雀监,因此可擴(kuò)展的方式,同時(shí)保持一切安全與最新的密碼學(xué)標(biāo)準(zhǔn)眨唬。將令牌(用戶角色和權(quán)限)存儲(chǔ)在令牌本身中会前,在發(fā)布請(qǐng)求的服務(wù)器無(wú)法訪問認(rèn)證數(shù)據(jù)源的分布式系統(tǒng)體系結(jié)構(gòu)中創(chuàng)造了巨大的收益。

BY DEJAN MILOSEVIC
原文:https://www.toptal.com/java/rest-security-with-jwt-spring-security-and-java
谷歌翻譯

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匾竿,一起剝皮案震驚了整個(gè)濱河市瓦宜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌岭妖,老刑警劉巖临庇,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異昵慌,居然都是意外死亡假夺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門废离,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侄泽,“玉大人,你說我怎么就攤上這事蜻韭。” “怎么了柿扣?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵肖方,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我未状,道長(zhǎng)俯画,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任司草,我火速辦了婚禮艰垂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘埋虹。我一直安慰自己猜憎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布搔课。 她就那樣靜靜地躺著胰柑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柬讨,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天崩瓤,我揣著相機(jī)與錄音,去河邊找鬼踩官。 笑死却桶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔗牡。 我是一名探鬼主播颖系,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蛋逾!你這毒婦竟也來了集晚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤区匣,失蹤者是張志新(化名)和其女友劉穎偷拔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亏钩,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡莲绰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了姑丑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛤签。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖栅哀,靈堂內(nèi)的尸體忽然破棺而出震肮,到底是詐尸還是另有隱情,我是刑警寧澤留拾,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布戳晌,位于F島的核電站,受9級(jí)特大地震影響痴柔,放射性物質(zhì)發(fā)生泄漏沦偎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一咳蔚、第九天 我趴在偏房一處隱蔽的房頂上張望豪嚎。 院中可真熱鬧,春花似錦谈火、人聲如沸侈询。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)妄荔。三九已至泼菌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間啦租,已是汗流浹背哗伯。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留篷角,地道東北人焊刹。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像恳蹲,于是被迫代替她去往敵國(guó)和親虐块。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

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