【JSP/SERVLET】Tomcat內置表單身份驗證

一、概述

    前面是扯犢子的,JSP/SERVLET基於HTTP規範,提供了幾種安全支持,BASIC、DIGEST、FORM、CLIENT-CERT,本文主要介紹一下FORM的安全支持開發,文末有一個小demo用於展示。

    因爲FORM方式比較少用,因此本文介紹的原理點到即止,並沒有特別特別深入,見諒。

    更多詳情,請參見《JSP/SERVLET核心編程》(新浪微盤,您找PDF的天堂···)


二、詳細

1. 原理簡述

    FROM聲明式安全基於表單驗證。

    簡述:用戶想要訪問某一個受保護的資源,如果用戶未登路,則將用戶導向一個特定格式的表單進行身份驗證,驗證通過則繼續訪問資源;驗證不通過,則將用戶導向一個提示頁面。

    關鍵點:

    a. 對受保護資源進行配置。本例是基於URL進行限制保護,因此需要在web.xml中配置受保護的URL;

    b. 特定格式的表單寫法。主要是三部分的固定寫法,一是表單action必須爲j_security_check,用戶名輸入input的name必須爲j_username,用戶密碼的輸入input的name必須爲j_password;

    c. 只要用戶登錄成功,並且支持cookie(會話cookie,跟session搭一塊幹活的那個cookie:JSESSIONID),那麼這個用戶名和密碼就會被保存到當前用戶的session中,後續只要用戶的會話cookie存在並且服務器session未過期,則一直驗證通過,否則驗證失敗,更多原理,請往下看;

    FROM驗證的安全性基於cookie/session機制的安全性,並且可以配置通過SSL傳輸,因此安全性還是比較高的,至少比BASIC的安全性高了不止一個等級。之前寫的一個小demo,手動實現BASIC驗證(不是基於JSP/SERVLET提供的封裝了的BASIC,而是其底層原汁原味id實現):點擊打開鏈接

    d. 侷限性。用戶的身份驗證,是基於服務器提供的用戶角色,以tomcat爲例,所有基於FORM的用戶安全驗證,都是基於tomcat user的安全驗證。也就是說,能夠通過用戶驗證的用戶配置,都是屬於tomcat_dir/conf/tomcat-user.xml中的<role rolename="xxx"/>配置和<user username="ooo" password="ooo" roles="xxx"/>。因此,基於表單驗證FORM的侷限性在於程序的可移植性,儘管代碼不需要重寫,但是不同的服務器的用戶規則不一樣,因此需要重新配置用戶;

2. demo講解

    業務邏輯:首頁index.jsp有一個超鏈,訪問一個受保護的路徑,如果用戶未被驗證,則自動跳轉到認證頁面,否則直接訪問資源;如果認證失敗,則自動跳轉到一個失敗提示頁面。

    整個FORM驗證的所有核心在於配置文件web.xml的配置,因此在理解demo業務邏輯的基礎上,本節的所有內容將圍繞配置文件展開。

2.1 首頁

    即index.jsp,這個頁面上有一個超鏈,用於訪問受保護資源,內容如下所示。

<a href="${pageContext.request.contextPath}/gif">查看羣相冊</a>

2.2 配置文件

    此時,因爲超鏈的訪問路徑“/gif”是受保護的,因此會判斷用戶是否已經驗證通過,判斷的條件是根據會話cookie找到對應的session,看session裏面是否已經存在j_username和j_password。下面分別來講解。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>春田花花同學會</display-name>
  <!-- 
  	一下配置都是基於FROM表單身份驗證的角度來說明的
  	爲了更好的閱讀,請重下網上看配置文件,謝謝合作!
   -->
  <!-- 
  	和form-error-page不同的是,當在授權頁面進行驗證的時候,如果username是一個合法的認證用戶
  	即username所在的role存在tomcat-users.xml中,但是這個role不具備訪問該資源的權限,則會返回403,跳轉到location指定的頁面
  	而form-error-page是認證失敗:1. 用戶名或密碼錯誤;2. username不存在tomcat-users.xml中
   -->
  <error-page>
    <error-code>403</error-code>
    <location>/security/fail.jsp</location>
  </error-page>
  <!-- 
  	login-config:
  		1. 當訪問受限資源但是還未驗證,則跳轉到form-login-page頁面,這個頁面的編寫需要固定的格式(理出爲不變格式化的內容,其他可選自填),形如
  		<form action="j_security_check">
  			<input type="text" name="j_username"/>
  			<input type="password" name="j_password"/>
  		</form>
  		如果有密碼,則表單最好是post提交
  		2. 當驗證失敗,即用戶名和密碼錯誤或用戶不在授權列表中,則直接跳轉到form-error-page指定頁面
  			這個頁面隨便編寫,目的是提示用戶
   -->
  <login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
      <form-login-page>/security/login.jsp</form-login-page>
      <form-error-page>/security/logfail.jsp</form-error-page>
    </form-login-config>
  </login-config>
  <!-- 
  	security-role:對應着tomcat-users.xml中的role配置
  	可選,有無均可以,配置主要是方便項目開發的人查看
   -->
  <security-role>
    <role-name>user-auth</role-name>
  </security-role>
  <!-- 安全約束配置:
  		display-name:可選,表示受保護的資源名
  		web-resource-collection:必選,至少一個,配置受保護的資源
  								本處配置的受保護資源爲:/gif
  		auth-constraint:授權約束,可選,role-name的value應該是在tomcat-users.xml中配置的<role rolename="xxx"/>
  						如果配置了auth-constraint,但是沒有設置value,則表示任何人都不能訪問
   -->
  <security-constraint>
    <display-name>R_file</display-name>
    <web-resource-collection>
      <web-resource-name>aiyou_gif</web-resource-name>
      <url-pattern>/gif</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>user-auth</role-name>
    </auth-constraint>
  </security-constraint>
  <!-- 首頁,這個頁面的超鏈請求到一個受保護的資源路徑(/gif,即上文中security-constraint中配置),於是被攔截到一個登陸認證的頁面 -->
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

2.3 實現原理

    查看form-lgoin-page頁面的請求頭和響應頭,推測j_username和j_password是保存於session中,但是查看sessionScope是空的,未能進一步驗證。但是根據HTTP的跡象來推測,應該是介樣的,有大神能進一步解答,請不吝賜教!

General
Remote Address:[::1]:8080
Request URL:http://localhost:8080/web02/j_security_check
Request Method:POST
Status Code:302 Found
Response Headers
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location: http://localhost:8080/web02/gif
Content-Length: 0
Date: Tue, 16 Jun 2015 09:54:39 GMT
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:36
Content-Type:application/x-www-form-urlencoded
Cookie:JSESSIONID=168CB17F9CF19F3615845B438332B7CD
Host:localhost:8080
Origin:http://localhost:8080
Referer:http://localhost:8080/web02/gif
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36
Form Data
view parsed
j_username=wangxinyan&j_password=123
    隨即驗證通過,進行/gif的資源訪問,此時會設置新的會話cookie,實際上在訪問授權頁面的時候,也會生成新的會話cookie。

General
Remote Address:[::1]:8080
Request URL:http://localhost:8080/web02/gif
Request Method:GET
Status Code:200 OK
Response Headers
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=6F12E8122EB68186270DC626974E24FE; Path=/web02/; HttpOnly
Cache-Control: private
Expires: Thu, 01 Jan 1970 08:00:00 CST
Content-Type: text/html;charset=UTF-8
Content-Length: 306
Date: Tue, 16 Jun 2015 09:54:39 GMT
Request Headers
GET /web02/gif HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36
Referer: http://localhost:8080/web02/gif
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cookie: JSESSIONID=168CB17F9CF19F3615845B438332B7CD

    基於Form的身份驗證,是需要瀏覽器支持cookie,否則機制會癱瘓。但是整個驗證的流程中HTTP透露的信息來看,並沒有看到set-cookie除了會話cookie JSESSIONID之外的其他cookie,因此並不是將認證信息存放於cookie中;但是整個流程中都存在會話cookie,因此猜測FORM機制是將認證信息存放於session,每次訪問cookie都會帶着session id到瀏覽器,如果訪問受保護資源,則瀏覽器通會過id找到session,session保存了認證信息,因此用戶可以直接訪問資源。

    並且,爲了輔助驗證,做了session.invalidate();的測試,發現當session失效以後,必須要重新驗證才能訪問受保護的資源,因此可以確定驗證信息是藉助於會話cookie/session機制來實現的,因此其安全性依賴於session和會話cookie的安全性,如果需要進一步提高安全性,在security-constraint中還可以配置SSL進行數據傳輸,因此,這種驗證方式還是比較安全的!


三、demo下載

    示例demo百度雲地址:點擊打開鏈接

    (該demo僅用於展示原理,其中還有很多不完善的地方,僅僅能作爲一個參考,謝謝!)


附註:

    參考資料:《JSP/SERVLET核心編程(第二版)》

    本文如有錯漏,煩請不吝指正,謝謝!

發佈了82 篇原創文章 · 獲贊 95 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章