Servlet 3.0 之 安全

Web應(yīng)用被應(yīng)用開(kāi)發(fā)者創(chuàng)建丽焊,這些開(kāi)發(fā)者給予啊奄、賣(mài)應(yīng)用,或者為了安裝到一個(gè)運(yùn)行時(shí)環(huán)境收叶,把應(yīng)用轉(zhuǎn)移應(yīng)用到一個(gè)部署者骄呼。應(yīng)用開(kāi)發(fā)者會(huì)把安全要求傳達(dá)給部署者和部署系統(tǒng)。這個(gè)信息可能會(huì)通過(guò)應(yīng)用的部署描述符或者在應(yīng)用代碼里使用注解明確地表達(dá)判没。
本章為了表達(dá)應(yīng)用的安全需求蜓萄,描述了Servlet容器安全機(jī)制、接口哆致、部署描述符和注解機(jī)制绕德。

一患膛、介紹

一個(gè)web應(yīng)用包含能被很多用戶(hù)訪問(wèn)的資源摊阀。這些資源通常在沒(méi)有保護(hù)和開(kāi)放網(wǎng)絡(luò)上傳輸,如Internet踪蹬。在這樣的環(huán)境中胞此,大量web應(yīng)用將會(huì)有安全需求。
雖然質(zhì)量保障和實(shí)現(xiàn)細(xì)節(jié)可能不同跃捣,servlet容器有機(jī)制和基礎(chǔ)設(shè)施來(lái)滿足共享下列特征的需求:

  • Authentication: 交流實(shí)體要向?qū)Ψ阶C明它們是在授權(quán)的特殊身份上訪問(wèn)漱牵。
  • Access control for resources: 與資源的交互被限制在用戶(hù)的集合中,或者為了強(qiáng)制一致性疚漆、可靠性或者可用性限制編程酣胀。
  • Data Integrity: 這被用來(lái)證明在數(shù)據(jù)傳輸過(guò)程中刁赦,信息沒(méi)有被第三方修改。
  • ** Confidentiality or Data Privacy:**這被用來(lái)保證信息僅對(duì)那些被授權(quán)的用戶(hù)訪問(wèn)闻镶。

二甚脉、聲明式安全

聲明式安全指表達(dá)一個(gè)應(yīng)用安全模型或者需求的方式,包括角色铆农,訪問(wèn)控制以及在一個(gè)應(yīng)用外部形勢(shì)的授權(quán)要求牺氨。部署描述符在web應(yīng)用中是主要的工具。
開(kāi)發(fā)者把應(yīng)用的邏輯安全需求映射到一個(gè)與具體運(yùn)行時(shí)環(huán)境相關(guān)的安全策略代表上墩剖。在運(yùn)行時(shí)中猴凹,servlet容器使用安全策略代表來(lái)強(qiáng)制認(rèn)證和授權(quán)。
安全模型應(yīng)用在web應(yīng)用中的靜態(tài)內(nèi)容部分和被客戶(hù)端請(qǐng)求的應(yīng)用中的servlets和filters上岭皂。當(dāng)一個(gè)servlet使用RequestDispatcher調(diào)用一個(gè)靜態(tài)資源或者使用一個(gè)forward或者includeservlet時(shí)郊霎,安全模型并不會(huì)應(yīng)用生效。

三爷绘、編程式安全

當(dāng)聲明式安全不足以表達(dá)應(yīng)用的安全模型時(shí)歹篓,編程式安全被安全意識(shí)應(yīng)用使用。編程式安全由HttpServletRequest接口的下列方法組成:
* authenticate
* login
* logout
* getRemoteUser
* isUserInRole
* getUserPrincipal

login方法允許一個(gè)應(yīng)用執(zhí)行用戶(hù)名和密碼集合(還有一種基于表單的登錄)揉阎。authenticate方法允許一個(gè)應(yīng)用從一個(gè)沒(méi)有限制的請(qǐng)求上下文中激起請(qǐng)求調(diào)用者的認(rèn)證庄撮。
logout方法允許一個(gè)應(yīng)用重置一個(gè)請(qǐng)求的調(diào)用身份。
getRemote方法返回與請(qǐng)求關(guān)聯(lián)的調(diào)用者名字毙籽。
isUserPrincipal方法決定與請(qǐng)求關(guān)聯(lián)的調(diào)用者是否是一個(gè)指定的安全角色洞斯。
getUserPrincipal方法決定了遠(yuǎn)端調(diào)用者的主要名字,并且返回一個(gè)與遠(yuǎn)端調(diào)用者對(duì)應(yīng)的java.security.Principal對(duì)象坑赡。在getUserPrincipal返回的Principal上調(diào)用getName方法會(huì)返回一個(gè)遠(yuǎn)端調(diào)用者的名字烙如。這些APIs允許servlets基于獲取的信息來(lái)決定業(yè)務(wù)邏輯。
如果沒(méi)有用戶(hù)已經(jīng)被授權(quán)毅否,getRemoteUser方法返回null亚铁,isUserInRole方法總會(huì)返回false,并且getUserPrincipal方法返回null螟加。
isUserInRole方法期望一個(gè)表示用戶(hù)角色名字的字符串參數(shù)徘溢。security-role-ref元素應(yīng)該在部署描述符中被聲明,并且有一個(gè)包含傳遞給方法的角色名字的role-name子元素捆探。一個(gè)security-role-ref元素應(yīng)該包含一個(gè)角色鏈接子元素然爆,它的值是用戶(hù)被映射到的安全角色的名字。當(dāng)決定調(diào)用的返回值時(shí)黍图,容器使用security-role-refsecurity-role的映射曾雕。
比如,把安全角色引用FOO映射到名字為manager的安全角色助被。語(yǔ)法如下
<security-role-ref>
<role-name>FOO</role-name>
<role-link>manager</role-link>
</security-role-ref>
這個(gè)例子中剖张,如果被屬于manager安全角色的用戶(hù)調(diào)用的servlet調(diào)用API方法isUserInRole切诀,結(jié)果將會(huì)是true。
如果沒(méi)有匹配一個(gè)security-rolesecurity-role-ref元素已經(jīng)被聲明搔弄,容器必須默認(rèn)對(duì)web應(yīng)用的security-role元素列表檢查role-name元素參數(shù)趾牧。isUserInRole方法參考這個(gè)列表來(lái)決定調(diào)用者是否被映射到一個(gè)安全角色。開(kāi)發(fā)者必須意識(shí)到這個(gè)默認(rèn)機(jī)制的使用在改變應(yīng)用中角色名字的時(shí)候限制靈活性肯污,改變角色名字不必重新編譯servlet來(lái)調(diào)用翘单。

四、編程式訪問(wèn)控制注解

本節(jié)定義了注解和apis蹦渣,用來(lái)配置Servlet容器強(qiáng)制的安全限制哄芜。

  1. @ServletSecurity Annotation
    @ServletSecurity注解為定義訪問(wèn)控制限制提供了一種替代機(jī)制,這等價(jià)于通過(guò)可移植部署描述符中的security-constraint元素聲明或者通過(guò)ServletRegistration接口的setServletSecurity方法編程式聲明柬唯。Servlet容器必須支持在實(shí)現(xiàn)了javax.servlet.Servlet 接口的類(lèi)上使用@ServletSecurity注解认臊。
    package javax.servlet.annotation;
    @Inherited
    @Documented
    @Target(value=TYPE)
    @Retention(value=RUNTIME)
    public @interface ServletSecurity {
    HttpConstraint value();
    HttpMethodConstraint[] httpMethodConstraints();
    }
    Table 1-1 ServletSecurity Interface
Element 描述 默認(rèn)
value HttpConstraint定義了應(yīng)用于所有沒(méi)出現(xiàn)在httpMethodConstraints返回?cái)?shù)組中的HTTP方法的保護(hù)。 @HttpConstraint
httpMethodConstraints HTTP方法具體限制的數(shù)組 {}

@HttpConstraint
@HttpConstraint注解在@ServletSecurity注解中被使用來(lái)代表應(yīng)用于所有HTTP協(xié)議方法的安全限制锄奢,一個(gè)對(duì)應(yīng)的@HttpMethodConstraint沒(méi)有為上述方法出現(xiàn)在@ServletSecurity注解中失晴。

package javax.servlet.annotation
@Documented
@Retention(value=RUNTIME)
public @interface HttpConstraint {
  ServletSecurity.EmptyRoleSemantic value();
  java.lang.String[] rolesAllowed();
  ServletSecurity.TransportGuarantee transportGuarantee();
}

Table 1-2 HttpConstraint接口

Element 描述 默認(rèn)
value 默認(rèn)的授權(quán)語(yǔ)義,僅當(dāng)rolesAllowed返回空數(shù)組時(shí)應(yīng)用拘央。 PERMIT
rolesAllowed 包含授權(quán)角色名字的一個(gè)數(shù)組 {}
transportGuarantee 數(shù)據(jù)保護(hù)要求涂屁,必須被請(qǐng)求到達(dá)的連接上被滿足 NONE

@HttpMethodConstraint
@HttpMethodConstraint注解在具體HTTP協(xié)議消息上代表安全限制的@ServletSecurity注解中被使用。

package javax.servlet.annotation
@Documented
@Retention(value=RUNTIME)
public @interface HttpMethodContraint {
  ServletSecurity.EmptyRoleSemantic value();
  java.lang.String[] rolesAllowed();
  ServletSecurity.TransportGuarantee transportGuarantee();
}
Element 描述 默認(rèn)
value HTTP協(xié)議方法名字
emptyRoleSemantic 默認(rèn)授權(quán)機(jī)制灰伟,僅當(dāng)rolesAllowed返回空字符串時(shí)應(yīng)用 PERMIT
rolesAllowed 包含已授權(quán)角色名字的一個(gè)數(shù)組 {}
transportGuarantee 數(shù)據(jù)保護(hù)需求拆又,必須被請(qǐng)求到達(dá)的連接滿足 NONE

@ServletSecurity注解可以在一個(gè)Servlet實(shí)現(xiàn)類(lèi)上被指明,并且它的值被為根據(jù)元注解@Inherited規(guī)則定義的子類(lèi)繼承栏账。@ServletSecurity注解的一個(gè)實(shí)例可以出現(xiàn)在一個(gè)Servlet實(shí)現(xiàn)類(lèi)上面帖族,并且@ServletSecurity注解一定不能在一個(gè)Java方法上被指定。
當(dāng)一個(gè)或者多個(gè)@HttpMethodConstraint注解在一個(gè)@ServletSecurity注解里面被定義挡爵,每個(gè)@HttpMethodConstraint定義了security-constraint竖般,它應(yīng)用在所有HTTP協(xié)議方法上,而不是那些一個(gè)對(duì)應(yīng)HttpMethodConstraint@ServletSecurity注解中被定義的方法上茶鹃。
定義在可移植部署描述符中的security-constraint元素對(duì)所有出現(xiàn)在限制里的url-patterns的有權(quán)限涣雕。
當(dāng)在可移植部署描述符中的一個(gè)security-constraint包含一個(gè)映射到一個(gè)用@ServletSecurity注解的類(lèi)的一個(gè)精確匹配的url-pattern,注解一定不能影響Servlet容器在pattern上的強(qiáng)行限制前计。
當(dāng)一個(gè)類(lèi)上沒(méi)有使用@ServletSecurity胞谭,應(yīng)用于從那個(gè)類(lèi)映射而來(lái)的一個(gè)servlet的訪問(wèn)策略(如果有的話)在對(duì)應(yīng)的部署描述符中被適用的security-constraint元素建立垃杖,或者除了任何這些元素男杈,通過(guò)ServletRegistration接口的setServletSecurity方法編程式地為目標(biāo)servlet建立。

  • 例子
    下列例子說(shuō)明了ServletSecurity注解的使用调俘。
    CODE EXAMPLE 4-1 對(duì)于所有的HTTP方法伶棒,沒(méi)有限制
    @ServletSecurity
    public class Example1 extends HttpServlet {
    }
    CODE EXAMPLE 4-2 對(duì)所有HTTP方法旺垒,沒(méi)有授權(quán)約束,加密傳輸要求
    @ServletSecurity(@HttpConstraint(transportGuarantee=TransportGuarantee.CONFIDENTIAL))
    public class Example2 extends HttpServlet {
    }
    CODE EXAMPLE 4-3 對(duì)所有HTTP方法肤无,所有訪問(wèn)都被拒絕
    @ServletSecurity(@HttpConstraint(EmptyRoleSemantic.DENY))
    public class Example3 extends HttpServlet {
    }
    CODE EXAMPLE 4-4 對(duì)所有HTTP方法先蒋,要求角色R1成員的權(quán)限約束
    @ServletSecurity(@HttpConstraint(rolesAllowed="R1"))
    public class Example4 extends HttpServlet {
    }
    CODE EXAMPLE 4-5 對(duì)所有除了GET和POST的HTTP方法,沒(méi)有約束宛渐;對(duì)GET和POST方法竞漾,要求Role R1成員的權(quán)限約束,加密傳輸要求窥翩。
    @ServletSecurity((httpMethodConstraints = { @HttpMethodConstraint(value="GET", rolesAllowed="R1"), @HttpMethodConstraint(value="POST", rolesAllowed="R1", transportGuarantee=TransportGuarantee.CONFIDENTIAL)})
    public class Example5 extends HttpServlet {
    }
    CODE EXAMPLE 4-6 對(duì)除了GET的所有HTTP方法要求Role R1中成員的權(quán)限約束业岁,對(duì)于GET,沒(méi)有約束寇蚊。
    @ServletSecurity(value = @HttpMethodConstraints(rolesAllowed = "R1"), httpMethodConstraints = @HttpMethodConstraint("Get"))
    public class Example6 extends HttpServlet {
    }
    CODE EXAMPLE 4-7 對(duì)于除了TRACE的所有HTTP方法笔时,要求Role R1中成員的權(quán)限約束;對(duì)于TRACE仗岸, 所有訪問(wèn)都拒絕允耿。
    @ServletSecurity(value = @HttpConstraint(rolesAllowed = "R1"), httpMethodConstraints = @HttpMethodConstraint(value="TRACE", emptyRoleSemantic = EmptyRoleSemantic.DENY))
    public class Example7 extends HttpServlet {
    }

  • 把@ServletSecurity映射到安全約束
    本節(jié)描述了@ServletSecurity注解到它等價(jià)表示,如security-constraint 元素的映射扒怖。它使用已存在的容器security-constraint執(zhí)行機(jī)制來(lái)促進(jìn)執(zhí)行较锡。@ServletSecurity注解的強(qiáng)制性等價(jià)于security-constraint元素的強(qiáng)制性。
    @ServletSecurity注解被用來(lái)定義一個(gè)方法依賴(lài)的@HttpConstraint盗痒,并且其后會(huì)跟著0個(gè)或者多個(gè)@HttpMethodConstraint說(shuō)明念链。方法依賴(lài)的約束應(yīng)用于所有沒(méi)有定義HTTP具體方法約束的HTTP方法。
    當(dāng)沒(méi)有包含@HttpMethodConstraint元素积糯,對(duì)應(yīng)包含一個(gè)不含http-method元素的web-resource-collection的單個(gè)security-constraint元素的@ServletSecurity注解適用于所有HTTP方法掂墓。
    下列例子描繪了一個(gè)不包含@HttpMethodConstraint注解作為單個(gè)security-constraint元素的@ServletSecurity注解表示。被對(duì)應(yīng)servlet定義的url-pattern元素將會(huì)被包含在web-resource-collection中看成,并且任何被包含的auth-constraintuser-data-constraint元素的出現(xiàn)和值將會(huì)通過(guò)@HttpConstraint值的映射被決定君编。
    CODE EXAMPLE 4-8 映射不包含@HttpMethodConstraint的@ServletSecurity
    @ServletSecurity(@HttpConstraint(rolesAllowed = "R1"))
    <security-constraint>
    <web-resource-collection>
    <url-pattern>...</url-pattern>
    </web-resource-collection>
    <auth-constraint>
    <role-name>Role1</role-name>
    <auth-constraint>
    </security-constraint>
    當(dāng)一個(gè)或者多個(gè)@HttpMethodConstraint元素被指定,方法依賴(lài)約束對(duì)應(yīng)單個(gè)security-constraint川慌,它包含一個(gè)為每個(gè)命名在具體方法下的HTTP方法限制于http-method-omission元素上的web-resource-collection吃嘿。每個(gè)@HttpMethodConstraint對(duì)應(yīng)于另外一個(gè)包含web-resource-collectionsecurity-constraint,這個(gè)web-resource-collection包含一個(gè)命名對(duì)應(yīng)HTTP方法的http-method元素梦重。下列例子描繪了由單個(gè)約束的@HttpMethodConstraint的一個(gè)@ServletSecurity注解到兩個(gè)security-constraint元素的映射兑燥。被對(duì)應(yīng)servlet定義的url-pattern元素將會(huì)被包含在web-resource-collection中,并且任何包含auth-constraintuser-data-constraint元素的出現(xiàn)和元素將會(huì)通過(guò)相關(guān)@HttpConstraint@HttpMethodConstraint值的映射來(lái)決定琴拧。
    CODE EXAMPLE 4-9 映射包含@HttpMethodConstraint的@ServletSecurity
    @ServletSecurity(value=@HttpConstraint(rolesAllowed = "Role1"), httpMethodConstraints = @HttpMethodConstraint(value = "TRACE", emptyRoleSemantic = EmptyRoleSemantic.DENY))
    <security-constraint>
    <web-resource-collection>
    <url-pattern>...</url-pattern>
    <http-method-omission>TRACE</http-method-omission>
    </web-resource-collection>
    <auth-constraint>
    <role-name>Role1</role-name>
    </auth-constraint>
    </security-constraint>
    <security-constraint>
    <web-resource-collection>
    <url-pattern>...</url-pattern>
    <http-method>TRACE</http-method>
    </web-resource-collection>
    </auth-constraint>
    </security-constraint>

  • 映射@HttpConstraint和@HttpMethodConstraint到XML
    本節(jié)描述了從@HttpConstraint@HttpMethodConstraint注解值到它們auth-constraintuser-data-constraint表示的映射降瞳。這些注解為了表達(dá)在部署描述符中使用的auth-constraintuser-data-constraint元素的等價(jià)性共享一個(gè)公用模型。這個(gè)模型由下列3個(gè)元素組成:

    • emptyRoleSemantic
      當(dāng)沒(méi)有角色被命名在rolesAllowed中時(shí),授權(quán)語(yǔ)義挣饥,PERMIT或者DENY應(yīng)用除师。這個(gè)元素的默認(rèn)值是PERMIT,并且DENY在聯(lián)合使用一個(gè)非空rolesAllowed列表中并不被支持扔枫。
    • rolesAllowed
      這是一個(gè)包含已授權(quán)角色名字的列表汛聚。當(dāng)這個(gè)列表為空,它的含義取決于emptyRoleSemantic的值短荐。當(dāng)包含在允許角色的列表中時(shí)倚舀,角色名字"*"沒(méi)有特殊含義。這個(gè)元素的默認(rèn)值是一個(gè)空列表忍宋。
    • TransportGuarantee
      無(wú)論是NONE或者CONFIDENTIAL瞄桨,數(shù)據(jù)保護(hù)需求必須被請(qǐng)求到達(dá)的連接滿足。這個(gè)元素等價(jià)于包含有對(duì)應(yīng)值的transport-guarantee元素的user-data-constraint讶踪。這個(gè)元素的默認(rèn)值是NONE芯侥。
      下列例子描繪了@HttpConstraint模型和web.xml中的auth-constrainttransport-guarantee元素之間的對(duì)應(yīng)關(guān)系。
      CODE EXAMPLE 4-10 emptyRoleSemantic=PERMIT,rolesAllowed={},transportGuarantee=NONE
      沒(méi)有限制
      CODE EXAMPLE 4-11 emptyRoleSemantic=PERMIT,rolesAllowed={},transportGuarantee=CONFIDENTIAL
      <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>
      CODE EXAMPLE 4-12 emptyRoleSemantic=PERMIT,rolesAllowed={Role1},transportGuarantee=NONE
      <auth-constraint>
      <security-role-name>Role1</security-role-name>
      </auth-constraint>
      CODE EXAMPLE 4-13 emptyRoleSemantic=PERMIT,rolesAllowed={Role1},transportGuarantee=CONFIDENTIAL
      <auth-constraint>
      <security-role-name>Role1</security-role-name>
      </auth-constraint>
      <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>
      CODE EXAMPLE 4-14 emptyRoleSemantic=DENY,rolesAllowed={},transportGuarantee=NONE
      <auth-constraint/>
      CODE EXAMPLE 4-15 emptyRoleSemantic=DENY,rolesAllowed={},transportGuarantee=CONFIDENTIAL
      <auth-constraint/>
      <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
      </user-data-constraint>
  1. ServletRegistration.Dynamic的setServletSecurity
    setServletSecurity方法可以在ServletContextListener中被用來(lái)定義應(yīng)用于為ServletRegistration定義的映射的安全約束乳讥。
    Collection<String> setServletSecurity(ServletSecurityElement arg)
    傳遞給serServletSecurityjavax.servlet.ServletSecurityElement參數(shù)類(lèi)似@ServletSecurity注解的ServletSecurity接口的結(jié)構(gòu)和模型柱查。Mapping @ServletSecurity to security-constraint節(jié)中定義的映射關(guān)系類(lèi)似于一個(gè)包含HttpConstraintElementHttpMethodConstraintElement值的ServletSecurityElement元素的映射,等價(jià)于security-constraint表示云石。
    setServletSecurity方法返回已經(jīng)是部署描述符(因此不會(huì)被調(diào)用影響)中security-constraint元素的精確目標(biāo)的URL模式的集合(可能為空)唉工。
    如果ServletsContext(ServletRegistration從這里獲取到)已經(jīng)被初始化,那么這個(gè)方法將會(huì)拋出一個(gè)IllegalStateException汹忠。
    當(dāng)部署描述符中的一個(gè)security-constraint包含一個(gè)url-pattern淋硝,這個(gè)url-pattern是一個(gè)被ServletRegistration映射的模式的精確匹配,那么調(diào)用ServletRegistration之上的setServletSecurity一定不能影響Servlet容器在模式上的強(qiáng)制約束宽菜。
    有上述列出的異常以及包含何時(shí)Servlet類(lèi)被@ServletSecurity注解谣膳,何時(shí)setServletSecurityServletRegistration上被調(diào)用,它會(huì)建立應(yīng)用于registration的url-pattern的安全約束铅乡。

五继谚、角色

一個(gè)安全角色是一個(gè)被應(yīng)用開(kāi)發(fā)者或者裝配器定義的用戶(hù)邏輯分組。當(dāng)應(yīng)用被部署阵幸,角色被一個(gè)開(kāi)發(fā)者映射到運(yùn)行時(shí)中的委托者或者組花履。
一個(gè)servlet容器為關(guān)聯(lián)一個(gè)基于主體安全屬性進(jìn)來(lái)的請(qǐng)求的主體強(qiáng)制執(zhí)行聲明式或者編程式安全。
這可以在下述方式的任意一種中發(fā)生:

  1. 一個(gè)開(kāi)發(fā)者已經(jīng)在運(yùn)行環(huán)境中把一個(gè)安全角色映射到一個(gè)用戶(hù)組挚赊。調(diào)用主體所在的用戶(hù)組從它們的安全屬性中被檢索诡壁。僅當(dāng)主體屬于安全角色已經(jīng)被開(kāi)發(fā)者映射到的用戶(hù)組,主體才是在安全角色中荠割。
  2. 一個(gè)開(kāi)發(fā)者已經(jīng)把一個(gè)安全角色映射到一個(gè)安全策略域中的一個(gè)主體名字妹卿。這種情況下,調(diào)用主體的主體名字從它們的安全屬性中檢索。僅當(dāng)主體名與安全角色被映射到的主體名一樣時(shí)纽帖,主體就在安全角色中宠漩。

六举反、認(rèn)證

一個(gè)web客戶(hù)端能夠使用下列機(jī)制中的一種來(lái)給一個(gè)web服務(wù)器驗(yàn)證用戶(hù)身份:

  • HTTP Basic Authentication
  • HTTP Digest Authentication
  • HTTPS Client Authentication
  • Form Based Authentication
  1. HTTP Basic Authentication
    HTTP Basic Authentication懊直,基于用戶(hù)名和密碼,是定義在HTTP/1.0規(guī)范中的認(rèn)證機(jī)制火鼻。一個(gè)web服務(wù)器請(qǐng)求一個(gè)web客戶(hù)端來(lái)驗(yàn)證這個(gè)用戶(hù)室囊。作為請(qǐng)求的一部分,web服務(wù)器會(huì)傳遞一個(gè)字符串realm魁索,用戶(hù)會(huì)在這個(gè)里面被認(rèn)證融撞。web客戶(hù)端從用戶(hù)獲取用戶(hù)名和密碼,然后把它們傳遞給web服務(wù)器粗蔚。web服務(wù)器會(huì)在具體的realm中驗(yàn)證用戶(hù)尝偎。
    Basic Authentication并不是一個(gè)安全認(rèn)證協(xié)議。用戶(hù)密碼以簡(jiǎn)單的base64編碼發(fā)送鹏控,并且目標(biāo)服務(wù)器沒(méi)有被驗(yàn)證致扯。額外的保護(hù)能夠緩解一些擔(dān)心:一個(gè)安全傳輸機(jī)制(HTTPS), 或者網(wǎng)絡(luò)級(jí)別的安全在一些部署場(chǎng)景下被應(yīng)用。
  2. HTTP Digest Authentication
    像HTTP Basic Authentication当辐,HTTP Digest Authentication基于一個(gè)用戶(hù)名和密碼驗(yàn)證一個(gè)用戶(hù)抖僵。然而,不像HTTP Basic Authentication缘揪,HTTP Digest Authentication不會(huì)在網(wǎng)絡(luò)上發(fā)送用戶(hù)密碼耍群。在HTTP Digest Authentication中,客戶(hù)端發(fā)送一個(gè)密碼的單向加密哈希(以及額外的數(shù)據(jù))找筝。盡管密碼不會(huì)在電纜上發(fā)送蹈垢,但是HTTP Digest Authentication要求明文密碼等價(jià)物對(duì)驗(yàn)證容器可用,以便容器能夠驗(yàn)證收到的通過(guò)計(jì)算預(yù)期數(shù)字的驗(yàn)證器袖裕。Servlet容器應(yīng)該支持HTTP_DIGEST驗(yàn)證耘婚。
  3. Form Based Authentication
    login screen的外觀和感覺(jué)在使用web瀏覽器的內(nèi)置驗(yàn)證機(jī)制時(shí)不能不同。本規(guī)范介紹了一個(gè)必須的form based authentication機(jī)制陆赋,它允許一個(gè)開(kāi)發(fā)者控制登錄界面的外觀和感覺(jué)沐祷。
    web應(yīng)用部署描述符包含了登錄表單的錯(cuò)誤頁(yè)面的入口。登錄表單必須包含用來(lái)輸入用戶(hù)名和密碼的域攒岛。這些域必須分別命名為j_usernamej_password赖临。
    當(dāng)一個(gè)用戶(hù)嘗試獲取受保護(hù)的web資源,容器會(huì)檢查用戶(hù)的身份認(rèn)證灾锯。如果用戶(hù)被認(rèn)證兢榨,并且擁有訪問(wèn)資源的權(quán)限,請(qǐng)求的web資源被激活,并且執(zhí)行它的一個(gè)引用被返回吵聪。
    如果用戶(hù)沒(méi)有被認(rèn)證凌那,所有下述步驟會(huì)出現(xiàn):
  4. 與安全約束相關(guān)的登錄表單被發(fā)送給客戶(hù)端,并且觸發(fā)認(rèn)證的URL路徑被容器存儲(chǔ)吟逝。
  5. 用戶(hù)被讓填寫(xiě)表單帽蝶,包括用戶(hù)名和密碼。
  6. 客戶(hù)端把表單以post方式發(fā)回給服務(wù)器块攒。
  7. 容器嘗試使用表單中的信息驗(yàn)證用戶(hù)励稳。
  8. 如果驗(yàn)證失敗,使用發(fā)送或者重定向的方式返回一個(gè)錯(cuò)誤頁(yè)面囱井,并且response的狀態(tài)碼被設(shè)置為200驹尼。
  9. 如果驗(yàn)證成功,認(rèn)證用戶(hù)的主體被檢查庞呕,看它是否在獲取資源的授權(quán)角色中新翎。
  10. 如果用戶(hù)被認(rèn)證,客戶(hù)端使用存儲(chǔ)的URL路徑被重定向到資源住练。
    發(fā)送給為通過(guò)驗(yàn)證的用戶(hù)的錯(cuò)誤頁(yè)面包含失敗的信息地啰。

Form Based Authentication如Basic Authentication一樣缺乏安全,因?yàn)橛脩?hù)密碼被作為普通文本被發(fā)送澎羞,并且目標(biāo)服務(wù)器沒(méi)有被驗(yàn)證髓绽。額外的保護(hù)能夠緩解一些擔(dān)憂:一個(gè)安全傳輸機(jī)制(HTTPS), 或者網(wǎng)絡(luò)級(jí)別的安全在一些部署場(chǎng)景下被應(yīng)用。

  1. 表單登錄注意事項(xiàng)
    基于表單的登錄和基于URL的會(huì)話跟蹤可能是有問(wèn)題的實(shí)現(xiàn)妆绞。僅當(dāng)會(huì)話被cookies或者SSL session信息維護(hù)的時(shí)候顺呕,基于表單的登錄才應(yīng)該被使用。
    為了進(jìn)行適當(dāng)?shù)尿?yàn)證括饶,登錄表單的動(dòng)作必須總是j_security_check株茶。做這個(gè)限制以便登錄表單無(wú)論是哪個(gè)資源都能正常工作,并且避免要求服務(wù)器指定表單之外的動(dòng)作域图焰。
    這是一個(gè)展示表單如何被編碼到HTML頁(yè)面中的例子:
    <form method="POST" action="j_security_check">
    <input type="text" name="j_username">
    <input type="password" name="j_password">
    </form>
    如果基于表單的登錄由于一個(gè)HTTP請(qǐng)求被調(diào)用启盛,原始請(qǐng)求的參數(shù)必須被容器保留,如果成功通過(guò)驗(yàn)證技羔,它會(huì)把調(diào)用重定向到一個(gè)請(qǐng)求的資源僵闯。
    如果用戶(hù)使用表單登錄通過(guò)驗(yàn)證,并且已經(jīng)創(chuàng)建一個(gè)HTTP會(huì)話藤滥,會(huì)話的超時(shí)或者非法導(dǎo)致用戶(hù)在后續(xù)請(qǐng)求必須引發(fā)用戶(hù)被重新認(rèn)證的場(chǎng)景下被登出鳖粟。登出的范圍與認(rèn)證的一樣:比如,如果容器支持單點(diǎn)登錄拙绊,如兼容Java EE技術(shù)的web容器向图,用戶(hù)將需要和位于web容器的任何web應(yīng)用重新認(rèn)證泳秀。

  2. HTTPS Client Authentication

使用HTTPS(HTTP over SSL)的終端用戶(hù)認(rèn)證是一個(gè)很強(qiáng)的認(rèn)證機(jī)制。這種機(jī)制需要客戶(hù)端擁有一個(gè)Public Key Certificate(PKC)榄攀。當(dāng)前PKCs在電商應(yīng)用中很有用嗜傅,并且在瀏覽器中的單點(diǎn)登錄中也很有用。

  1. 其它容器認(rèn)證機(jī)制
    Servlet容器應(yīng)該提供一個(gè)公共接口檩赢,可以通過(guò)部署的應(yīng)用的容器被用來(lái)集成和配置額外的HTTP消息層認(rèn)證機(jī)制吕嘀。這些接口應(yīng)該被提供給締約方使用,而不是給容器提供商(包括應(yīng)用開(kāi)發(fā)者漠畜,系統(tǒng)管理員币他,和系統(tǒng)集成者)坞靶。
    為了促進(jìn)便攜實(shí)現(xiàn)和額外容器認(rèn)證機(jī)制的集成憔狞,推薦所有Servlet容器實(shí)現(xiàn)給容器提供的Java 認(rèn)證SPI的Servlet Container Profile。SPI可以在這里下載:http://www.jcp.org/en/jsr/detail?id=196彰阴。

七瘾敢、認(rèn)證信息的服務(wù)器跟蹤

在運(yùn)行時(shí)環(huán)境中角色被映射到的當(dāng)前安全身份(如用戶(hù)和組)是具體環(huán)境,而不是具體應(yīng)用尿这,它期望是:

  1. 做web應(yīng)用部署的環(huán)境中的登錄機(jī)制和策略簇抵。
  2. 能夠使用相同的認(rèn)證信息來(lái)對(duì)所有部署在同一個(gè)容器的應(yīng)用代表一個(gè)主體。
  3. 僅當(dāng)跨越了一個(gè)安全策略域邊界射众,才需要用戶(hù)的重新認(rèn)證碟摆。
    因此,一個(gè)servlet容器被要求在容器級(jí)別跟蹤認(rèn)證信息(而不是web應(yīng)用級(jí)別)叨橱。這允許對(duì)一個(gè)web應(yīng)用已經(jīng)認(rèn)證的用戶(hù)訪問(wèn)被其它擁有同樣安全身份的容器管理的資源典蜕。

八、指定安全約束

安全約束是定義web內(nèi)容保護(hù)的一個(gè)聲明方式罗洗。一個(gè)安全約束與認(rèn)證關(guān)聯(lián)愉舔,用戶(hù)數(shù)據(jù)與web資源上的HTTP操作關(guān)聯(lián)。一個(gè)安全約束伙菜,在部署描述中被security-constration表示轩缤,由下列元素組成:

  • web資源集合(部署描述符中的web-resource-collection
  • 認(rèn)證約束(部署描述符中的auth-constraint
  • 用戶(hù)數(shù)據(jù)約束(部署描述符中的user-data-constraint
    HTTP操作和安全約束應(yīng)用于的web資源被一個(gè)或者多個(gè)web資源集合識(shí)別。一個(gè)web資源集合由下列元素組成:
  • URL patterns(部署描述符中的url-pattern
  • HTTP方法(部署描述符中的http-methodhttp-method-omission元素)
    一個(gè)認(rèn)證約束為認(rèn)證和認(rèn)證角色允許執(zhí)行約束請(qǐng)求的名字建立一個(gè)要求贩绕。一個(gè)用戶(hù)必須是允許執(zhí)行約束請(qǐng)求的角色的一個(gè)成員火的。特殊的角色名字"*"是對(duì)定義在部署描述符中定義的所有角色名字的一個(gè)簡(jiǎn)稱(chēng)。一個(gè)沒(méi)有命名角色的認(rèn)證約束表明訪問(wèn)約束請(qǐng)求一定不能在任何環(huán)境下被允許淑倾。一個(gè)認(rèn)證約束由下列元素組成:
  • 角色名字(部署描述符role-name
    一個(gè)用戶(hù)數(shù)據(jù)約束建立一個(gè)必要條件:一個(gè)約束的請(qǐng)求在受保護(hù)傳輸層連接上被接收馏鹤。所需保護(hù)的強(qiáng)度被傳輸保證的值定義。一個(gè)INTEGRAL的傳輸保證被用來(lái)為內(nèi)容完整性建立一個(gè)必要條件踊淳,并且一個(gè)CONFIDENTIAL的傳輸保證被用來(lái)為加密簡(jiǎn)歷一個(gè)必要條件假瞬。NONE的傳輸保證表明當(dāng)在任何包含一個(gè)未受保護(hù)的連接上被接收時(shí)陕靠,容器必須接收約束的請(qǐng)求。一個(gè)用戶(hù)數(shù)據(jù)約束有下列元素組成:
  • transport guarantee(部署描述符中的transport-guarantee
    如果沒(méi)有認(rèn)證約束應(yīng)用于一個(gè)請(qǐng)求脱茉,容器必須接收請(qǐng)求剪芥,而不需要用戶(hù)認(rèn)證。如果沒(méi)有用戶(hù)數(shù)據(jù)約束應(yīng)用于一個(gè)請(qǐng)求琴许,當(dāng)在任何包含一個(gè)未受保護(hù)的連接上被接收時(shí)税肪,容器必須接收請(qǐng)求
  1. 聯(lián)合約束
    為了聯(lián)合約束的目的,當(dāng)沒(méi)有HTTP方法在集合中被命名榜田,或者集合特地在一個(gè)被包含的http-method元素中特地命名了HTTP方法益兄,或者集合包含一個(gè)或者更多http-method-omission元素,沒(méi)有元素命名這個(gè)HTTP方法時(shí)箭券,一個(gè)HTTP方法會(huì)在一個(gè)web-resource-collection中出現(xiàn)净捅。
    當(dāng)一個(gè)url-pattern和HTTP方法對(duì)在多個(gè)安全約束下出現(xiàn)在聯(lián)合(比如在一個(gè)web-resource-collection中)中,這個(gè)約束(在pattern和方法上)通過(guò)聯(lián)合單獨(dú)的約束來(lái)定義辩块。對(duì)相同pattern和方法出現(xiàn)的聯(lián)合約束規(guī)則如下:
  • 命名角色或者通過(guò)名字"*"說(shuō)明角色的認(rèn)證約束的聯(lián)合將會(huì)產(chǎn)生單個(gè)約束中角色名字的并集蛔六。一個(gè)不包含一個(gè)認(rèn)證約束的安全約束將會(huì)結(jié)合命名或者暗示角色的認(rèn)證約束來(lái)允許未認(rèn)證約束。一個(gè)沒(méi)有命名角色的認(rèn)證約束的特殊例子將聯(lián)合其它任何約束來(lái)重寫(xiě)它們的影響并且訪問(wèn)被阻止废亭。
  • 應(yīng)用于一個(gè)普通url-patternuser-data-constraintshttp-method的聯(lián)合將會(huì)產(chǎn)生被單個(gè)約束接收的連接類(lèi)型的并集国章。一個(gè)并不包含一個(gè)user-data-constraint的安全約束將會(huì)與其它user-data-constraint聯(lián)合來(lái)讓未保護(hù)的連接類(lèi)型成為一個(gè)可接收的連接類(lèi)型。
  1. 例子
    下列例子說(shuō)明了約束的聯(lián)合以及它們到一個(gè)應(yīng)用約束表格的轉(zhuǎn)換豆村。假設(shè)一個(gè)部署描述符包含下列安全限制:
    <security-constraint>
    <web-resource-collection>
    <web-resource-name>preclued methods</web-resource-name>
    <url-pattern>/</url-pattern>
    <url-pattern>/acme/wholesale/
    </url-pattern>
    <url-pattern>/acme/retail/</url-pattern>
    <http-method-omission>GET</http-method-omission>
    <http-method-omission>POST</http-method-omission>
    </web-resource-collection>
    <auth-constraint/>
    </security-constraint>
    <security-constraint>
    <web-resource-collection>
    <web-resource-name>wholesale</web-resource-name>
    <url-pattern>/acme/wholesale/
    </url-pattern>
    <http-method>GET</http-method>
    <http-method>PUT</http-method>
    </web-resource-collection>
    <auth-constraint>
    <role-name>SALEACLERK</role-name>
    </auth-constraint>
    </security-constraint>
    <security-constraint>
    <web-resource-collection>
    <web-resource-name>wholesale 2</web-resource-name>
    <url-pattern>/acme/wholesale/</url-pattern>
    <http-method>GET</http-method>
    <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
    <role-name>CONTRACTOR</role-name>
    </auth-constraint>
    <user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
    </security-constraint>
    <security-constraint>
    <web-resource-collection>
    <web-resource-name>retail</web-resource-name>
    <url-pattern>/acme/retail/
    </url-pattern>
    <http-method>GET</http-method>
    <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
    <role-name>CONTRACTOR</role-name>
    <role-name>HOMEOWNER</role-name>
    </auth-constraint>
    </security-constraint>
    這個(gè)假想部署描述符的轉(zhuǎn)換將會(huì)產(chǎn)生下表中定義的約束:
    TABLE 安全約束表
url-pattern http-method permitted roles 支持的連接類(lèi)型
/* 除了GET液兽、POST的所有方法 訪問(wèn)拒絕 沒(méi)有約束
/acme/wholesale/* 除了GET兄世、POST的所有方法 訪問(wèn)拒絕 沒(méi)有約束
/acme/wholesale/* GET CONTRACTOR SALESCLERK 沒(méi)有約束
/acme/wholesale/* POST CONTRACTOR CONFIDENTIAL
/acme/retail/* 除了GET盛正、POST的所有方法 訪問(wèn)拒絕 沒(méi)有約束
/acme/retail/* GET CONTRACTOR HOMEOWNER 沒(méi)有約束
/acme/retail/* POST CONTRACTOR HOMEOWNER 沒(méi)有約束
  1. 處理請(qǐng)求
    當(dāng)servlet容器接收一個(gè)請(qǐng)求拍棕,它將會(huì)使用Use of URL Paths中描述的算法來(lái)選擇是請(qǐng)求URI的最佳匹配的url-pattern上定義的約束(如果有)剑勾。如果沒(méi)有約束被選擇颠黎,容器將會(huì)接收請(qǐng)求喳资。否則容器將會(huì)決定請(qǐng)求的HTTP方法是否在選擇的模式上被約束掉伏。如果不是巩剖,請(qǐng)求將會(huì)被接收适滓。否則敦迄,請(qǐng)求必須在url-pattern上滿足應(yīng)用于HTTP方法的約束。下列兩條規(guī)則必須滿足將被接收的請(qǐng)求并且分發(fā)給關(guān)聯(lián)servlet凭迹。
  2. 請(qǐng)求被接收連接上的特點(diǎn)必須滿足至少一個(gè)被約束定義的支持連接類(lèi)型罚屋。如果這條規(guī)則不被滿足,容器將會(huì)拒絕請(qǐng)求并且會(huì)重定向到HTTPS端口嗅绸。
  3. 請(qǐng)求的認(rèn)證特點(diǎn)必須滿足任何認(rèn)證和通過(guò)約束定義的角色要求脾猛。如果這條規(guī)則由于訪問(wèn)被拒絕(通過(guò)一個(gè)認(rèn)證約束沒(méi)有命名角色)而不被滿足,請(qǐng)求將會(huì)按照禁止?fàn)顟B(tài)被拒絕并且403(SC_FORBIDDEN)狀態(tài)碼將會(huì)被返回給用戶(hù)鱼鸠。如果訪問(wèn)被限制允許角色并且請(qǐng)求還沒(méi)有被認(rèn)證猛拴,請(qǐng)求將會(huì)因?yàn)槲凑J(rèn)證被拒絕羹铅,并且401(SC_UNAUTHORIZED)狀態(tài)碼將會(huì)返回給原因認(rèn)證。如果訪問(wèn)被限制允許角色并且請(qǐng)求的認(rèn)證身份不是這些角色中任何一個(gè)的成員愉昆,請(qǐng)求將會(huì)因?yàn)榻贡痪芙^职员,并且一個(gè)403(SC_FORBIDDEN)狀態(tài)碼將會(huì)被返回給用戶(hù)。

九跛溉、默認(rèn)策略

默認(rèn)地焊切,訪問(wèn)資源不需要被認(rèn)證。當(dāng)包含是請(qǐng)求URI最佳匹配的url-pattern的安全約束(如果有)在請(qǐng)求的HTTP方法上結(jié)合實(shí)施一個(gè)auth-constraint(命名角色)時(shí)芳室,認(rèn)證是必要的专肪。相似地,一個(gè)受保護(hù)的傳輸并不必要堪侯,除非應(yīng)用于請(qǐng)求上的安全約束在請(qǐng)求的HTTP方法上結(jié)合實(shí)施一個(gè)user-data-constraint(帶一個(gè)受保護(hù)的transport-guarantee)嚎尤。

十、登錄和登出

把一個(gè)請(qǐng)求分發(fā)給servlet引擎時(shí)抖格,容器建立請(qǐng)求的調(diào)用者身份诺苹。調(diào)用者身份在整個(gè)請(qǐng)求處理過(guò)程中保持不變咕晋,或者直到應(yīng)用在request上成功調(diào)用authenticate雹拄,login或者logout
請(qǐng)求處理期間被記錄到一個(gè)應(yīng)用中掌呜,由于可以通過(guò)調(diào)用request上的getRemoteUser或者getUserPrincipal滓玖,精確對(duì)應(yīng)一個(gè)與請(qǐng)求關(guān)聯(lián)的合法非空調(diào)用者身份。一個(gè)來(lái)自任意這些方法的null返回值表明調(diào)用者在請(qǐng)求處理時(shí)沒(méi)有被記錄進(jìn)應(yīng)用中质蕉。
容器可以穿件一個(gè)HTTP會(huì)話對(duì)象來(lái)跟蹤登錄狀態(tài)势篡。如果一個(gè)開(kāi)發(fā)者創(chuàng)建了一個(gè)會(huì)話,同時(shí)一個(gè)用戶(hù)沒(méi)有被認(rèn)證模暗,那么容器會(huì)認(rèn)證這個(gè)用戶(hù)禁悠,登錄之后對(duì)開(kāi)發(fā)者代碼的會(huì)話可見(jiàn)性必須是同一個(gè)會(huì)話對(duì)象,這個(gè)對(duì)象在登錄出現(xiàn)之前被創(chuàng)建兑宇,以便沒(méi)有會(huì)話信息的丟失碍侦。

翻譯自 Java Servlet Specification
Version 3.0 Rev a
Author:Rajiv Mordani
Date: December 2010

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市隶糕,隨后出現(xiàn)的幾起案子瓷产,更是在濱河造成了極大的恐慌,老刑警劉巖枚驻,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件濒旦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡再登,警方通過(guò)查閱死者的電腦和手機(jī)尔邓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)晾剖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人梯嗽,你說(shuō)我怎么就攤上這事钞瀑。” “怎么了慷荔?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵雕什,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我显晶,道長(zhǎng)贷岸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任磷雇,我火速辦了婚禮偿警,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘唯笙。我一直安慰自己螟蒸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布崩掘。 她就那樣靜靜地躺著七嫌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苞慢。 梳的紋絲不亂的頭發(fā)上诵原,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音挽放,去河邊找鬼绍赛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛辑畦,可吹牛的內(nèi)容都是我干的吗蚌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼纯出,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蚯妇!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起潦刃,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤侮措,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后乖杠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體分扎,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年胧洒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了畏吓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墨状。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖菲饼,靈堂內(nèi)的尸體忽然破棺而出肾砂,到底是詐尸還是另有隱情,我是刑警寧澤宏悦,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布镐确,位于F島的核電站,受9級(jí)特大地震影響饼煞,放射性物質(zhì)發(fā)生泄漏源葫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一砖瞧、第九天 我趴在偏房一處隱蔽的房頂上張望息堂。 院中可真熱鬧,春花似錦块促、人聲如沸荣堰。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)振坚。三九已至,卻和暖如春逃片,著一層夾襖步出監(jiān)牢的瞬間屡拨,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工褥实, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人裂允。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓损离,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親绝编。 傳聞我的和親對(duì)象是個(gè)殘疾皇子僻澎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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

  • 本章為部署描述符中Web容器支持詳細(xì)描述Java Servlet 規(guī)范3.0版本要求。部署描述符在應(yīng)用開(kāi)發(fā)者十饥,應(yīng)用...
    Lucky_Micky閱讀 2,004評(píng)論 0 0
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理窟勃,服務(wù)發(fā)現(xiàn),斷路器逗堵,智...
    卡卡羅2017閱讀 134,651評(píng)論 18 139
  • 從三月份找實(shí)習(xí)到現(xiàn)在秉氧,面了一些公司,掛了不少蜒秤,但最終還是拿到小米汁咏、百度亚斋、阿里、京東攘滩、新浪帅刊、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,240評(píng)論 11 349
  • Servlet Interface 是Java Servlet API的核心抽象漂问。所有的servlets都直接或者...
    Lucky_Micky閱讀 1,697評(píng)論 2 2
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,804評(píng)論 6 342