10.3 Servlet API integration

本節(jié)介紹如何將Spring Security?與servlet API集成。?servletapi-xml示例應(yīng)用程序演示了這些方法的用法。

10.3.1?Servlet 2.5+ Integration

HttpServletRequest.getRemoteUser()

HttpServletRequest.getRemoteUser() 將返回SecurityContextHolder.getContext().getAuthentication().getName()的結(jié)果智厌,后者通常是當(dāng)前用戶(hù)名。如果要在應(yīng)用程序中顯示當(dāng)前用戶(hù)名,這將非常有用娩梨。此外,可以使用檢查這是否為空來(lái)指示用戶(hù)是否已經(jīng)過(guò)身份驗(yàn)證或是匿名的览徒。知道用戶(hù)是否經(jīng)過(guò)身份驗(yàn)證對(duì)于確定是否應(yīng)顯示某些UI元素很有用(即狈定,只有在用戶(hù)經(jīng)過(guò)身份驗(yàn)證時(shí)才應(yīng)顯示注銷(xiāo)鏈接)。

HttpServletRequest.getUserPrincipal()

HttpServletRequest.getUserPrincipal()?將返回SecurityContextHolder.getContext().getAuthentication()的結(jié)果习蓬。這意味著它是一個(gè)身份驗(yàn)證纽什,在使用用戶(hù)名和基于密碼的身份驗(yàn)證時(shí),它通常是UsernamePasswordAuthenticationToken的實(shí)例躲叼。如果您需要有關(guān)用戶(hù)的其他信息稿湿,這將非常有用。例如押赊,您可能創(chuàng)建了一個(gè)自定義的UserDetailsService饺藤,該服務(wù)返回一個(gè)包含您的用戶(hù)名字和姓氏的自定義用戶(hù)詳細(xì)信息包斑。您可以通過(guò)以下方式獲得此信息:

Authentication auth = httpServletRequest.getUserPrincipal();

// assume integrated custom UserDetails called MyCustomUserDetails

// by default, typically instance of UserDetails

MyCustomUserDetails userDetails = (MyCustomUserDetails) auth.getPrincipal();

String firstName = userDetails.getFirstName();

String lastName = userDetails.getLastName();

應(yīng)該注意的是,在整個(gè)應(yīng)用程序中執(zhí)行如此多的邏輯通常是不好的做法涕俗。相反罗丰,應(yīng)該集中它以減少Spring Security?和servlet API之間的任何耦合。

HttpServletRequest.isUserInRole(String)

HttpServletRequest.isUserInRole(String)?將確定SecurityContextHolder.getContext().getAuthentication().getAuthorities() 是否包含傳遞給 isUserInRole(string)的角色的授權(quán)再姑。通常萌抵,用戶(hù)不應(yīng)將“ROLE_”前綴傳入此方法,因?yàn)樗亲詣?dòng)添加的元镀。例如绍填,如果要確定當(dāng)前用戶(hù)是否具有“ROLE_ADMIN”權(quán)限,可以使用以下內(nèi)容:

boolean isAdmin = httpServletRequest.isUserInRole("ADMIN");

這可能有助于確定是否應(yīng)顯示某些UI組件栖疑。例如讨永,只有當(dāng)當(dāng)前用戶(hù)是管理員時(shí),才能顯示管理員鏈接遇革。

10.3.2?Servlet 3+ Integration

以下部分介紹Spring Security集成的servlet 3方法卿闹。

HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse)

HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse)?方法可以用來(lái)確保用戶(hù)已經(jīng)完成了身份驗(yàn)證。如果它們未經(jīng)過(guò)身份驗(yàn)證萝快,則配置的 AuthenticationEntryPoint?將用于請(qǐng)求用戶(hù)進(jìn)行身份驗(yàn)證(即重定向到登錄頁(yè))锻霎。

HttpServletRequest.login(String,String)

HttpServletRequest.login(String,String)方法使用當(dāng)前的?AuthenticationManager?對(duì)用戶(hù)進(jìn)行身份驗(yàn)證。例如揪漩,下面將嘗試使用用戶(hù)名“user”和密碼“password”進(jìn)行身份驗(yàn)證:

try{

????httpServletRequest.login("user","password");

}catch(ServletException e) {

????// fail to authenticate

}

如果希望Spring Security?處理失敗的身份驗(yàn)證嘗試旋恼,則不必捕獲ServletException。

HttpServletRequest.logout()

HttpServletRequest.logout()?方法可用于注銷(xiāo)當(dāng)前用戶(hù)奄容。

通常這意味著?SecurityContextHolder?將被清除冰更,HttpSession?將失效,任何“Remember Me”身份驗(yàn)證將被清除嫩海,等等冬殃。但是,配置的Logoothandler實(shí)現(xiàn)將根據(jù)您的Spring安全配置而變化叁怪。需要注意的是审葬,在調(diào)用HttpServletRequest.logout() 之后,您仍然在改寫(xiě)響應(yīng)奕谭。通常會(huì)重定向到歡迎頁(yè)面涣觉。

AsyncContext.start(Runnable)

AsynchContext.start(Runnable)?方法,用于確保將憑據(jù)傳播到新線(xiàn)程血柳。使用Spring Security 的并發(fā)支持官册,Spring Security?將重寫(xiě)AsyncContext.Start(Runnable),以確保在處理Runnable時(shí)使用當(dāng)前的SecurityContext难捌。例如膝宁,以下內(nèi)容將輸出當(dāng)前用戶(hù)的身份驗(yàn)證:

final AsyncContext async = httpServletRequest.startAsync();

async.start(new Runnable() {

? ? public void run() {

? ? ? ? Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

? ? ? ? try {

? ? ? ? ? ? final HttpServletResponse asyncResponse = (HttpServletResponse) async.getResponse();

? ? ? ? ? ? asyncResponse.setStatus(HttpServletResponse.SC_OK);

? ? ? ? ? ? asyncResponse.getWriter().write(String.valueOf(authentication));

? ? ? ? ? ? async.complete();

? ? ? ? } catch(Exception e) {

? ? ? ? ? ? throw new RuntimeException(e);

? ? ? ? }

? ? }

});

Async Servlet Support

如果您使用的是基于Java的配置鸦难,那么您已經(jīng)準(zhǔn)備好了。如果您使用的是XML配置员淫,則需要進(jìn)行一些更新合蔽。第一步是確保已更新web.xml以至少使用3.0架構(gòu),如下所示:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

version="3.0">

</web-app>

接下來(lái)介返,您需要確保為處理異步請(qǐng)求設(shè)置了SpringSecurityFilterChain拴事。

<filter>

<filter-name>springSecurityFilterChain</filter-name>

<filter-class>

? ? org.springframework.web.filter.DelegatingFilterProxy

</filter-class>

<async-supported>true</async-supported>

</filter>

<filter-mapping>

<filter-name>springSecurityFilterChain</filter-name>

<url-pattern>/*</url-pattern>

<dispatcher>REQUEST</dispatcher>

<dispatcher>ASYNC</dispatcher>

</filter-mapping>

就是這樣!現(xiàn)在圣蝎,Spring安全性將確保SecurityContext也在異步請(qǐng)求上傳播刃宵。

那么它是如何工作的呢?如果你真的不感興趣徘公,可以跳過(guò)這一部分的其余部分牲证,否則請(qǐng)繼續(xù)閱讀。其中大部分都內(nèi)置于servlet規(guī)范中步淹,但是Spring Security?做了一些調(diào)整从隆,以確保異步請(qǐng)求能夠正常工作诚撵。在Spring Security3.2之前缭裆,只要提交HttpServletResponse,就會(huì)自動(dòng)保存SecurityContextHolder中的SecurityContext寿烟。這可能導(dǎo)致異步環(huán)境中出現(xiàn)問(wèn)題澈驼。例如,考慮以下內(nèi)容:

httpServletRequest.startAsync();

new Thread("AsyncThread") {

? ? @Override

? ? public void run() {

? ? ? ? try {

? ? ? ? ? ? // Do work

? ? ? ? ? ? TimeUnit.SECONDS.sleep(1);

? ? ? ? ? ? // Write to and commit the httpServletResponse

? ? ? ? ? ? httpServletResponse.getOutputStream().flush();

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? }

}.start();

問(wèn)題是這個(gè)線(xiàn)程不知道Spring Security筛武,所以SecurityContext不會(huì)傳播給它缝其。這意味著當(dāng)我們提交HttpServletResponse?時(shí)沒(méi)有SecuriytContext。當(dāng)Spring Security在提交httpServletResponse時(shí)自動(dòng)保存SecurityContext時(shí)徘六,它將丟失我們的登錄用戶(hù)内边。

從3.2版開(kāi)始,Spring Security就足夠智能待锈,一旦調(diào)用了HttpServletRequest.StartAsync()漠其,就不會(huì)在提交HttpServletResponse時(shí)自動(dòng)保存SecurityContext。

10.3.3?Servlet 3.1+ Integration

以下部分介紹Spring Security集成的servlet 3.1方法竿音。

HttpServletRequest#changeSessionId()

HttpServletRequest.changeSessionId()是servlet 3.1及更高版本中防止會(huì)話(huà)固定攻擊的默認(rèn)方法和屎。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市春瞬,隨后出現(xiàn)的幾起案子柴信,更是在濱河造成了極大的恐慌,老刑警劉巖宽气,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件随常,死亡現(xiàn)場(chǎng)離奇詭異潜沦,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)绪氛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)止潮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人钞楼,你說(shuō)我怎么就攤上這事喇闸。” “怎么了询件?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵燃乍,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我宛琅,道長(zhǎng)刻蟹,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任嘿辟,我火速辦了婚禮舆瘪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘红伦。我一直安慰自己英古,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布昙读。 她就那樣靜靜地躺著召调,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蛮浑。 梳的紋絲不亂的頭發(fā)上唠叛,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音沮稚,去河邊找鬼艺沼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蕴掏,可吹牛的內(nèi)容都是我干的障般。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼囚似,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼剩拢!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起饶唤,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤徐伐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后募狂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體办素,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡角雷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了性穿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勺三。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖需曾,靈堂內(nèi)的尸體忽然破棺而出吗坚,到底是詐尸還是另有隱情,我是刑警寧澤呆万,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布商源,位于F島的核電站,受9級(jí)特大地震影響谋减,放射性物質(zhì)發(fā)生泄漏牡彻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一出爹、第九天 我趴在偏房一處隱蔽的房頂上張望庄吼。 院中可真熱鬧,春花似錦严就、人聲如沸总寻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)废菱。三九已至技矮,卻和暖如春抖誉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衰倦。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工袒炉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人樊零。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓我磁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親驻襟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子夺艰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

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