徹底掌握CORS跨源資源共享

本文來自于公眾號鏈接: 徹底掌握CORS跨源資源共享

)

本文接上篇公眾號文章:徹底理解瀏覽器同源策略SOP

一.概述

在云時代,各種SAAS應(yīng)用層出不窮,各種互聯(lián)網(wǎng)API接口越來越豐富硕舆,H5技術(shù)在微信小程序球凰、支付寶小程序来颤、Hybird中大行其道,所有的這些都離不開跨源訪問德崭。

CORS即跨源資源共享(Cross-Origin Resource Sharing)斥黑,是由W3C組織維護(hù)的處于穩(wěn)定狀態(tài)的瀏覽器跨源訪問規(guī)范接癌,被現(xiàn)代主流版本瀏覽器充分支持缨叫。在普通的web應(yīng)用跨源訪問server的場景下,CORS是最優(yōu)的跨源訪問方案有咨。對比其他的方案座享,如iframe標(biāo)簽嵌套方案不夠安全婉商,JSONP方案功也只支持GET方法,CORS的安全性高且功能完善渣叛。

什么是跨源訪問

現(xiàn)代瀏覽器都支持同源策略SOP丈秩。假如有網(wǎng)站:

A的web頁調(diào)用B的資源,此時因?yàn)锳和B的源不同淳衙,就發(fā)生了跨源訪問蘑秽。根據(jù)SOP規(guī)范饺著,在默認(rèn)情況下A的web頁是無法訪問到B的資源的。CORS在盡量保證安全的前提下肠牲,放寬了SOP限制幼衰,使得瀏覽器可以跨源訪問服務(wù)器資源。

關(guān)于SOP細(xì)則缀雳,請參考上篇公眾號文章徹底理解瀏覽器同源策略SOP

插圖:corsflow

除了最常用的XMLHttpRequest(AJAX)或Fetch發(fā)起的跨源請求渡嚣,web元素如Form表單、跨源加載css肥印、web字體严拒、甚至3D圖形引擎webGL跨源加載紋理等等都可以發(fā)起跨源請求。

本文通過Form表單和AJAX跨源訪問代碼示例來講解CORS的來龍去脈竖独。雖然代碼示例是基于Java技術(shù)棧的Spring Boot+Spring Security框架,但是CORS流程原理是多語言棧通用的挤牛,因此不影響其他語言棧的同學(xué)閱讀莹痢。

一.Form默認(rèn)支持跨源訪問

Form實(shí)際上是默認(rèn)支持跨源訪問的,CORS在發(fā)展過程中一直在努力保持不與Form沖突墓赴,這個問題常常被開發(fā)者忽略竞膳。

Form是從HTTP1.0就存在的歷史遺留技術(shù),至今仍然被廣泛應(yīng)用诫硕。Form沒有AJAX功能強(qiáng)大坦辟,產(chǎn)生危害的可能性更小,支持的Http方法只有GET和POST章办,支持的Http頭很少而且還無法自定義擴(kuò)展锉走。其次,F(xiàn)orm請求成功后是全頁面刷新的藕届,當(dāng)使用Form提交到其他地址挪蹭,原頁面會重定向到其他地址,使得腳本無法獲取新頁面中的內(nèi)容做惡意篡改休偶。瀏覽器有足夠的理由認(rèn)為即使Form跨源訪問也是安全的梁厉。

我們以Java程序?yàn)槔w驗(yàn)下Form默認(rèn)支持的跨源訪問踏兜。

新建一個Spring Boot工程词顾,命名為“back-end-spring-boot",端口號為8080碱妆,依賴spring-boot-starter-web包肉盹,新增一個controller接口:

@RestController
public class SampleController {

    @GetMapping("/sample")
    public String getSample() {
        return "getSample";
    }

    @PostMapping("/sample")
    public String post(HttpServletRequest request) {
        return "post";
    }

    @DeleteMapping("/sample")
    public String delete(String sampleId) {
        return "delete";
    }

    @PutMapping("/sample")
    public String put(HttpServletRequest request) {
        return "put";
    }
}

SampleController提供了基礎(chǔ)的GET,POST山橄,PUT垮媒,DELETE方法類型的接口舍悯。
在工程目錄“resources/static/”下新建一個html5文件index.html,添加一個Form表單:

<form action="http://localhost:8080/sample" method="POST" >
    <div >
        <label for="name">Enter your name: </label>
        <input type="text" name="name" id="name" required>
    </div>
    <div >
        <label for="name">Enter your password: </label>
        <input type="text" name="password" id="password" required>
    </div>
    <div>
        <input type="submit" value="提交">
    </div>
</form>

運(yùn)行

  1. 運(yùn)行工程“back-end-spring-boot"
  2. 雙擊index.html睡雇,使用瀏覽器的file協(xié)議打開頁面萌衬。此時index.html和“back-end-spring-boot"是不同的源,可以模擬跨源訪問它抱。
  3. 點(diǎn)擊index.html的“提交”按鈕秕豫。
    插圖;form

瀏覽器成功重定向到:http://localhost:8080/sample 观蓄,并且頁面顯示字符串“post”混移。
插圖;formresult侮穿。

此示例演示了工程“back-end-spring-boot"中并沒有任何跨源策略歌径,F(xiàn)orm就可以進(jìn)行跨源訪問。

二.AJAX使用CORS跨源訪問

與Form不同亲茅,XMLHttpRequest(AJAX)功能更靈活更強(qiáng)大回铛,也更容易帶來安全風(fēng)風(fēng)險。AJAX可以實(shí)現(xiàn)web的局部刷新克锣,并且每次請求可以直接讀取響應(yīng)內(nèi)容茵肃,瀏覽器認(rèn)為AJAX的跨源訪問是危險的。

1.跨源訪問錯誤

使用AJAX無法直接跨源訪問server袭祟。
在index.xml增加一個模擬AJAX請求的按鈕:

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script language="javascript" type="text/javascript">
    function getSample() {
        $.ajax({
            type: 'GET',
            url: 'http://localhost:8080/sample',
            success: function (result) {
                alert(result);
            },
            error: function (error, msg) {
                alert(msg);
            }
        });
    }
</script>
<button onclick="getSample()">getSample</button>

雙擊index.html验残,使用瀏覽器查看,此時點(diǎn)擊getSample按鈕巾乳,在瀏覽器控制臺會提示一個跨源訪問錯誤:
圖片:withoutCORS

在同源策略限制下您没,瀏覽器雖然可以訪問到server端,server端也會正常返回數(shù)據(jù)胆绊,但是返回的數(shù)據(jù)會被瀏覽器攔截紊婉,web應(yīng)用只能收到一個跨源訪問錯誤信息。

2.使用CORS跨源訪問

如果AJAX想跨源訪問server辑舷,需要在server端配置CORS規(guī)則喻犁。

server端工程“back-end-spring-boot”支持CORS,
首先引入Spring Security包:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

再增加security配置類:

@EnableWebSecurity(debug = true)
@Profile("defaultCORS")
public class SecurityConfigDefaultCORS extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().permitAll();
        http.cors();
    }
    
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
    
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }
}

Spring Boot框架的 org.springframework.web.filter.CorsFilter 過濾器實(shí)現(xiàn)了CORS功能何缓。如果又使用了Spring Security肢础,只需要調(diào)用http.cors(),框架就會自動構(gòu)造一個CorsFilter的實(shí)例。CorsConfigurationSource實(shí)例負(fù)責(zé)CORS具體規(guī)則的全局配置碌廓。其中“corsConfiguration.addAllowedOrigin("*");”表示允許所有源訪問传轰,實(shí)際是server端返回時候添加“Access-Control-Allow-Origin”響應(yīng)頭。

重新啟動工程“back-end-spring-boot”谷婆,再雙擊index.html慨蛙,在瀏覽器查看辽聊,點(diǎn)擊getSample按鈕,彈出框顯示:
插圖:ajaxcors

此時AJAX可以使用GET方法跨源訪問http://localhost:8080/sample接口期贫。

大部分Web Server只需要一個過濾器類就實(shí)現(xiàn)了CORS的處理邏輯跟匆。以Java技術(shù)棧的tomcat為例,它提供了 org.apache.catalina.filters.CorsFilter 來實(shí)現(xiàn)CORS功能通砍。對于不便修改源碼的項目玛臂,直接修改tomcat配置就可以快速支持CORS。

3.CORS的響應(yīng)頭Access-Control-Allow-Methods控制允許的Http方法

上個示例AJAX使用GET方法進(jìn)行了跨源訪問封孙。如果同時要支持POST方法跨源訪問迹冤,則修改server端的響應(yīng)頭Access-Control-Allow-Methods,來控制允許訪問的HTTP方法虎忌。如:

Access-Control-Allow-Methods: POST, GET, OPTIONS

表示允許瀏覽器使用 POST, GET 和 OPTIONS 方法發(fā)起請求泡徙。

在index.html增加:

<script language="javascript" type="text/javascript">
    function postSample() {
        var postParam = {
            'username':"a",
            'password':"a"
        };
        $.ajax({
            type: 'POST',
            url: 'http://localhost:8080/sample',
            data:postParam,
            success: function (result) {
                alert(result);
            },
            error: function (error, msg) {
                alert(msg);
            }
        });
    }
</script>
<button onclick="postSample()">postSample</button>

雙擊index.html,在瀏覽器打開頁面后點(diǎn)擊"postSample"按鈕膜蠢,瀏覽器報錯:
插圖:cors錯誤

再security配置類的corsConfigurationSource方法中增加:

corsConfiguration.addAllowedMethod("*");

星號代表允許所有Http方法如GET锋勺,POST,OPTIONS狡蝶,DELETE等等。

并禁用csrf保護(hù)(csrf保護(hù)不是本篇重點(diǎn)贮勃,禁用后贪惹,可以減少不必要的干擾)

http.csrf().disable();

刷新index.html,在瀏覽器打開頁面后點(diǎn)擊"postSample"按鈕寂嘉,瀏覽器顯示:
插圖:postsuccess

此時就可以跨源訪問"postSample"接口了奏瞬。

4.CORS的響應(yīng)頭Access-Control-Allow-Headers控制允許攜帶的Http頭

除了可以控制允許的Http方法,在server端的響應(yīng)頭Access-Control-Allow-Headers可以控制跨源請求中允許攜帶的Http頭泉孩。如:

Access-Control-Allow-Headers: X-TEST, Y-TEST

表示跨源訪問時允許攜帶自定義頭X-TEST和Y-TEST

在index.html的postSample方法請求時候傳遞自定義頭:

headers: {
    'X-TEST':"test header"
},

刷新index.html頁面,點(diǎn)擊postSample按鈕會報錯:
插圖:allowheader

再在security的配置類增加:

corsConfiguration.addAllowedHeader("*");

星號(“*”)表示的允許所有請求頭硼端。

再次訪問則提示成功,并且server端可以調(diào)用“request.getHeader("X-TEST")”獲取自定義的Http頭信息 寓搬。

5.CORS的其他響應(yīng)頭

CORS還定義了其他server端可配置的響應(yīng)頭珍昨,通過這些響應(yīng)頭可以細(xì)粒度地控制跨源訪問規(guī)則。具體的有:

  • Access-Control-Allow-Origin:允許跨源訪問的源列表
  • Access-Control-Allow-Methods:允許跨源訪問的Http方法
  • Access-Control-Allow-Headers:允許跨源訪問時候攜帶的Http頭
  • Access-Control-Max-Age:預(yù)檢請求緩存的時間
  • Access-Control-Expose-Headers:server端允許客戶端訪問的響應(yīng)頭列表
  • Access-Control-Allow-Credentials:允許瀏覽器攜帶如cookie等用戶驗(yàn)證信息
Access-Control-Expose-Headers

其中的Access-Control-Expose-Headers在前后端分離架構(gòu)中經(jīng)常會用到句喷,比如登錄成功后server端經(jīng)常通過Http響應(yīng)頭回傳給瀏覽器一個token,如:

Authorization: 71f0ed0aa56d480a81ce78eb8cc99605

并且設(shè)置:

 corsConfiguration.addExposedHeader(HttpHeaders.AUTHORIZATION);

此時瀏覽器調(diào)用getResponseHeader()可以獲取到Authorization中的token值镣典,然后緩存這個token,表示用戶已經(jīng)登錄成功唾琼。

需要注意兄春,CORS安全性規(guī)則定義Access-Control-Expose-Headers不可以設(shè)置為星號“*”。

Access-Control-Allow-Credentials

其中的Access-Control-Allow-Credentials最常用的場景是瀏覽器跨源訪問時可以攜帶跨源的cookie锡溯,也就是攜帶用戶驗(yàn)證狀態(tài)赶舆。比如在單點(diǎn)退出場景下哑姚,server A退出時候同時,瀏覽器同時跨源調(diào)用server B的退出接口芜茵,此時配置:

corsConfiguration.setAllowCredentials(true);

并且AJAX調(diào)用時候配置:

$.ajax({
    ...
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true,: true,
    ...
})

此時Server A跨源訪問此時Server B時叙量,可以攜帶著此時Server B的cookie,此時Server B就可以拿到這個cookie進(jìn)行退出操作了夕晓。

三.CORS流程原理

CORS定義了一系列Http頭宛乃,定義了瀏覽器和Server之間的交互流程,使得CORS實(shí)現(xiàn)瀏覽器可以安全地跨源訪問server蒸辆,并且server可以細(xì)粒度地控制跨源訪問規(guī)則征炼。

對于Http頭來說,除了server端的響應(yīng)頭之外躬贡,CORS還規(guī)定了瀏覽器端的請求頭:

  • Origin:表示發(fā)起的跨源請求的源谆奥。如A跨源訪問B,則Origin的值是A的源(schema拂玻,host酸些,port),server端只有接收到攜帶Origin頭的請求時檐蚜,才會認(rèn)為這是一個跨源請求魄懂。
  • Access-Control-Request-Method:用在預(yù)檢請求過程中,代表實(shí)際請求的Http方法類型
  • Access-Control-Request-Headers:用在預(yù)檢請求過程中闯第,代表實(shí)際請求需要攜帶的自定義Http頭

CORS協(xié)議是由最初的access-control訪問提案逐漸演變過來的市栗,因此這些CORS都以“Access-Control-”為前綴。

對于跨源訪問流程來說咳短,CORS本來可以簡化為大致兩個步驟:

  1. 瀏覽器發(fā)起OPTIONS方法類型的預(yù)檢請求(Preflight)
  2. server端驗(yàn)證預(yù)檢請求通過后填帽,瀏覽器再發(fā)送真實(shí)請求

然而CORS為了同時兼容Form和AJAX、為了向下兼容HTTP協(xié)議和瀏覽器咙好,無法做到這么簡單篡腌。比如FORM表單也必須可以跨源訪問卻無法支持OPTIONS類型的預(yù)檢請求。

因此CORS將瀏覽器請求分為兩種:

  • 簡單跨源請求(Simple Cross-Origin Request)
  • 需要預(yù)檢的跨源請求(Cross-Origin Request with Preflight)

1.簡單跨源請求

簡單跨源請求主要是為了使Form表單等技術(shù)也支持跨源訪問勾效,使得CORS協(xié)議可以向上和向下兼容嘹悼。
同時滿足“簡單HTTP方法”、“簡單HTTP頭”的請求层宫,可視為“簡單請求”绘迁。

簡單HTTP方法(Simple Method)
  • GET
  • HEAD
  • POST

GET,POST卒密,HEAD方法是HTTP1.0協(xié)議就定義的缀台,F(xiàn)orm也只支持GET和POST。

簡單HTTP頭(Simple Header)
  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type取值為:
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded

注意POST跨源請求時哮奇,如果Content-Type不是上述的三種膛腐,則不是簡單跨源請求睛约。

無論是“簡單HTTP方法”還是“簡單HTTP頭”都與form表單支持的功能吻合。

2.需要預(yù)檢的跨源請求

除了簡單跨源請求之外的其他跨源請求哲身,不需要被form表單支持辩涝,所以跨源訪問時候不用再考慮對form表單做特殊地兼容。

CORS規(guī)定在實(shí)際跨源請求前勘天,需要先執(zhí)行預(yù)檢請求(Preflight)怔揩。預(yù)檢請求使用的是Http方法是OPTIONS,只有server端處理預(yù)檢請求通過后脯丝,瀏覽器才可以接著發(fā)送實(shí)際請求商膊。

插圖:preflightProccess

CORS之所以使用預(yù)檢請求,是因?yàn)轭A(yù)檢請求杜絕了不安全server被跨源訪問的可能性宠进。對server端來說晕拆,一旦能正確響應(yīng)預(yù)檢請求,就說明server是理解CORS且針對CORS做過專門處理材蹬。如果沒有preflight而是直接依靠服務(wù)器的響應(yīng)來確定請求是否正確实幕,從而使瀏覽器不必為單個調(diào)用發(fā)出兩個請求。這樣貌似簡化了操作堤器,但實(shí)際上相當(dāng)于假定服務(wù)器首先正確地驗(yàn)證了請求昆庇,然而實(shí)際上許多服務(wù)器沒有這樣做,這就是CSRF攻擊大行其道的原因闸溃。沒有preflight請求的話就會有不安全server存在的可能性整吆。

點(diǎn)擊postSample按鈕,查看瀏覽器控制臺:
插圖:prefight

CORS是個“圓滑”的協(xié)議圈暗,向下和向后的兼容性很好,假如有一天HTTP協(xié)議正式告別了歷史遺留的FORM裕膀,那么CORS協(xié)議不需要做大改動员串,只需讓瀏覽器把簡單請求的概念合并為復(fù)雜請求就可以了,CORS將會進(jìn)化得更加簡潔和高效昼扛。

四.最佳配置實(shí)踐

1.全局配置與接口單獨(dú)配置

一般實(shí)現(xiàn)的server端技術(shù)都可以對CORS進(jìn)行全局配置和每個接口單獨(dú)配置寸齐。全局配置便捷方便,一次配置抄谐,所有接口都生效渺鹦。每個接口單獨(dú)配置則可以精確地配置每個接口的跨源訪問規(guī)則。實(shí)際項目上建議采用全局配置和每個接口單獨(dú)配置相結(jié)合的方式來實(shí)踐蛹含。

以Java技術(shù)棧的SpringBoot+SpringSecurity框架為例毅厚。一般采用全局配置CorsConfigurationSource和接口級細(xì)粒度配置@CrossOrigin結(jié)合的方式,最終生效的屬性值是全局和細(xì)粒度配置合并后的值浦箱,需要注意Spring提供的默認(rèn)合并規(guī)則是“采用最大匹配進(jìn)行合并”吸耿,具體可以參考:org.springframework.web.cors.CorsConfiguration類的combine(CorsConfiguration)方法祠锣,

如:
多值屬性Access-Control-Allow-Headers,當(dāng)全局配置CorsConfigurationSource為:

corsConfiguration.addAllowedHeader("Authorization");

而接口單獨(dú)配置為:

@CrossOrigin(allowedHeaders = "*")

則最終生效的是星號“*”咽安。

而對于單值屬性Access-Control-Allow-Credentials伴网,則以@CrossOrigin為準(zhǔn)。

Access-Control-Allow-Credentials要尤其要注意妆棒,因?yàn)橐坏╅_啟就相當(dāng)于暴露了用戶相關(guān)信息澡腾,比如用戶的cookie和csrf token。一般全局配置將Access-Control-Allow-Credentials設(shè)置為false糕珊。在需要跨源傳遞用戶狀態(tài)的接口單獨(dú)配置為true动分。

2.其他

Access-Control-Allow-Origin等支持星號的響應(yīng)頭在生產(chǎn)環(huán)境不要使用星號“*”,要根據(jù)實(shí)際跨源訪問需求配置真實(shí)的列表放接。

本位的源碼上傳到了Github刺啦,地址:https://github.com/andyzhaozhao/spring-security-sample-cors

技術(shù)是不斷發(fā)展的,要用動態(tài)的眼光看待技術(shù)問題纠脾。能夠和技術(shù)不斷成長本身時間很美妙的事情

如果有任何問題和建議玛瘸,可以右下角點(diǎn)贊后評論,我們會第一時間回復(fù)苟蹈。

五.參考

更多干貨都在《spring security實(shí)戰(zhàn)》

官方資料

其他參考

關(guān)于schema和protocal描述的是一個東西
關(guān)于Orign定義

本為官方出處微信公眾號: 碼聞


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末糊渊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子慧脱,更是在濱河造成了極大的恐慌渺绒,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件菱鸥,死亡現(xiàn)場離奇詭異宗兼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)氮采,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門殷绍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鹊漠,你說我怎么就攤上這事主到。” “怎么了躯概?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵登钥,是天一觀的道長。 經(jīng)常有香客問我娶靡,道長牧牢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮结执,結(jié)果婚禮上度陆,老公的妹妹穿的比我還像新娘。我一直安慰自己献幔,他們只是感情好懂傀,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蜡感,像睡著了一般蹬蚁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上郑兴,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天犀斋,我揣著相機(jī)與錄音,去河邊找鬼情连。 笑死叽粹,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的却舀。 我是一名探鬼主播虫几,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼挽拔!你這毒婦竟也來了辆脸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤螃诅,失蹤者是張志新(化名)和其女友劉穎啡氢,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體术裸,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倘是,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了袭艺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搀崭。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖匹表,靈堂內(nèi)的尸體忽然破棺而出门坷,到底是詐尸還是另有隱情宣鄙,我是刑警寧澤袍镀,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站冻晤,受9級特大地震影響苇羡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鼻弧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一设江、第九天 我趴在偏房一處隱蔽的房頂上張望锦茁。 院中可真熱鬧,春花似錦叉存、人聲如沸码俩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稿存。三九已至,卻和暖如春瞳秽,著一層夾襖步出監(jiān)牢的瞬間瓣履,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工练俐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袖迎,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓腺晾,卻偏偏與公主長得像燕锥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子丘喻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

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