安全性是Web應用程序開發工作中最關鍵的問題之一。在基於servlet的應用程序裡,保護應用程序資源的辦法有兩種:一是對應用程序進行配置(web.XML),二是使用Java代碼硬編碼到程序中。前一種方法使用配置文件,該方法很靈活,這是因為通過使用配置文件,無需改寫任何代碼就可以改變安全策略,是一種常見的手段。而Struts 2是基於servlet技術的,所以Struts 2的安全策略也可以使用配置文件進行靈活的配置。
配置安全策略時,有兩個概念需要清楚的區分 ,用戶和角色,簡單的說用戶為使用計算機的人,可以是個人或組織。角色是一個抽象的概念,泛指職務或者權限。例如,張三,李四,王五三個人,有職員、主管和經理三個職務(權限),張三是用戶,張三可以是主管職務,代表張三這個用戶含有主管的權利。
不同的servlet容器所提供的用戶和角色管理機制是不相同的。我使用的是Tomcat服務器,它提供的用戶和角色管理機制文件是在其安裝目錄下的conf目錄中的tomcat-users.XML文件,可以在這個文件裡完成對用戶和角色的編輯。例如:
- <tomcat-users>
- <role rolename="tomcat"/>
- <role rolename="role1"/>
- <user username="tomcat" passWord="tomcat" roles="tomcat"/>
- <user username="both" passWord="tomcat" roles="tomcat,role1"/>
- <user username="role1" passWord="tomcat" roles="role1"/>
- </tomcat-users>
這個文件定義了2個角色(tomcat和role1)和3名用戶(tomcat、both和role1)。你可以在tomcat-users.XML文件裡定義任意多個用戶和角色。
使用Struts 2保護應用程序的資源
Struts 2應用程序的安全策略是通過部署web.XML文件中的security-constraint元素實現的,該元素的語法定義:
- <!ELEMENT security-constraint (display-name?, web-resource-collection+, auth-constraint?, user-data-constraint?)>
- <!ELEMENT display-name (#PCDATA)>
- <!ELEMENT web-resource-collection (web-resource-name, description?, url-pattern*, http-method*)>
- <!ELEMENT auth-constraint (description?, role-name*)>
- <!ELEMENT user-data-constraint (description?, transport-guarantee)>
該語法說明了,security-constraint元素可以有一個可選的display-name子元素,至少一個web-resource-collection子元素,一個可選的auth-constraint子元素和一個可選的user-data-constraint子元素。
web-resource-collection子元素是用來列出打算保護的Web資源,具體的做法是為這些資源設置URL限制,它是通過設置web-resource-collection元素包含的子元素實現的:
◆ web-resource-name:是與受保護資源相關聯的名稱。該子元素為必須元素。
◆ description:對給定資源的描述。這個子元素為可選元素。
◆ url-pattern:用來設置URL表達式,與這個URL表達式相匹配的URL地址指向的資源將受到保護。該子元素為至少有一個,為必須元素。
◆ http-method:用來表明哪些HTTP方法將受到限制,例如設置為GET那麼所有的GET請求就將受到限制。該元素為可選元素。
auth-constraint元素用於指定可以訪問該資源用戶角色集合。如果沒有指定auth-constraint元素,就將安全約束應用於所有角色。它包含下面幾個子元素:
◆ description:描述。該元素是可選元素。
◆ role-name:可以訪問保護資源的用戶角色。該元素可以有多個。
◆ user-data-constraint元素用來設置怎樣保護在客戶端和Web容器之間傳遞的數據。
◆ description: 描述。可選元素。
◆ transport-guarantee :該元素有以下幾個值
1. NONE,這意味著應用不需要傳輸保證。
2. INTEGRAL,意味著服務器和客戶端之間的數據必須以某種方式發送,而且在傳送中數據不能被篡改。
3. CONFIDENTIAL,這意味著傳輸的數據必須加密。
配置完畢security-constraint元素的基本信息,大致為下面的格式:
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>Admin Arew</web-resource-name>
- <url-pattern>*.action</url-pattern>
- </web-resource-collection>
- <auth-constraint>
- <role-name>myeclipseWeb</role-name>
- </auth-constraint>
- </security-constraint>
這個security-constraint元素的效果為:只要與表達式"*.action"匹配的請求不是來自擁有"myeclipseWeb"權限的用戶,Web容器就會阻斷它。在這裡還可以使用http-method元素,阻斷特定方法的請求,因為沒有使用會阻斷所有方法提交的請求。
設置完安全策略後,還需要設置讓用戶有機會提供證明,證明自己有權限訪問這個受限資源的登陸方法。允許使用的登陸方法使用login-config元素設置,下面為login-config元素的語法定義:
- <!ELEMENT login-config (auth-method?, realm-name?, form-login-config?)>
- <!ELEMENT auth-method (#PCDATA)>
- <!ELEMENT realm-name (#PCDATA)>
- <!ELEMENT form-login-config (form-login-page, form-error-page)>
login-config子元素的描述如下:
◆ auth-method指定用來驗證用戶身份的方法。它的值為下面的一個:BASIC、DIGEST、FORM或 CLIENT-CERT
◆ realm-name指定HTTP Basic驗證中在標准登陸框中顯示的一條提示。
◆ form-login-config元素是在<auth-method>元素值為"FORM"時使用的。它是指定基於表單的登錄中應該使用的登錄頁面和出錯頁面。如果沒有使用基於表單的驗證,則忽略這些元素。這個元素的定義如下,其中form-login-page用於指定顯示登錄頁面的資源路徑, form-error-page則用於指定用戶登錄失敗時顯示出錯頁面的資源路徑。
- <!ELEMENT form-login-config (form-login-page, form-error-page)>
- <!ELEMENT form-login-page (#PCDATA)>
- <!ELEMENT form-error-page (#PCDATA)>
設置完登陸方法後,還應該使用security-role元素,注冊允許用來訪問受保護資源所有角色。在該元素內部使用一個role-name子元素來注冊一個角色。例如:
- <security-role>
- <role-name>myeclipseWeb</role-name>
- </security-role>
注冊了一個"myeclipseWeb"的角色。
演示示例:使用BASIC登陸方法驗證用戶身份
1.我使用的Servlet容器是Tomcat,找到它的目錄下conf目錄中的tomcat-users.XML文件打開內容如下:
- <?XML version='1.0' encoding='utf-8'?>
- <tomcat-users>
- <role rolename="myeclipseWeb"/>
- <role rolename="myeclipseWebservices"/>
- <user username="webservices" passWord="webservices-pwd" roles="myeclipseWebservices"/>
- <user username="admin" passWord="admin-pwd" roles="myeclipseWeb,myeclipseWebservices"/>
- <user username="web" passWord="web-pwd" roles="myeclipseWeb"/>
- </tomcat-users>
我使用的IDE是myEclipse9.0,它配置好Tomcat下的tomcat-users.XML文件內容如上,我直接使用它了,你也可以添加自己的角色和用戶。該文件定義了2個角色和3個用戶,每一個用戶都由自己的角色(或者說權限,可以有多重權限)。
2.創建Web項目,找到web.XML,配置它,使它支持Struts 2並且啟動Struts 2的安全策略
- <?XML version="1.0" encoding="UTF-8"?>
- <web-app id="WebApp_9" version="2.4"
- XMLns="http://Java.sun.com/XML/ns/J2EE"
- XMLns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/XML/ns/J2EE http://Java.sun.com/XML/ns/J2EE/web-app_2_4.xsd">
- <display-name>Struts Blank</display-name>
- <filter>
- <filter-name>struts2</filter-name>
- <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <welcome-file-list>
- <welcome-file>index.Html</welcome-file>
- </welcome-file-list>
- <!-- 配置應用程序需要保護的資源與什麼角色才可以訪問它 -->
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>Admin Arew</web-resource-name>
- <url-pattern>*.action</url-pattern>
- </web-resource-collection>
- <auth-constraint>
- <role-name>myeclipseWeb</role-name>
- </auth-constraint>
- </security-constraint>
- <!-- 注冊可以訪問保護資源的角色 -->
- <security-role>
- <role-name>myeclipseWeb</role-name>
- </security-role>
- <security-role>
- <role-name>myeclipseWebservices</role-name>
- </security-role>
- <!-- 設置登錄方法 -->
- <login-config>
- <auth-method>BASIC</auth-method>
- <realm-name>User Basic Authentication</realm-name>
- </login-config>
- </web-app>
3. 創建接收一個字段信息的動作類:
- public class SecureAction extends ActionSupport {
- private static final long serialVersionUID = 1961430702313132722L;
- private String username;
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- @Override
- public String execute()
- {
- return SUCCESS;
- }
- }
4. 創建struts.XML配置文件,聲明動作
- <?XML version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//apache Software Foundation//DTD Struts Configuration 2.0//EN"
- "http://struts.apache.org/dtds/struts-2.0.dtd">
- <struts>
- <package name="securePackage" extends="struts-default">
- <action name="secure" class="struts2.action.SecureAction">
- <result name="success">/index.JSP</result>
- </action>
- </package>
- </struts>
5. 創建輸入頁面input.JSp和結果頁面index.JSP
input.JSP:
- <body>
- <s:form action="secure">
- <s:textfIEld name="username" label="Enter your name"></s:textfIEld>
- <s:submit value="submit"></s:submit>
- </s:form>
- </body>
index.JSP
- <body>
- <s:property value="username"/>,Welcome
- </body>
6.測試效果,在浏覽器輸入:http://localhost:8081/SecureTest/input.JSP,得到如下界面:輸入"Tom",點擊"submit"按鈕
看到了登陸框了吧,此時我們要訪問的資源是一個受限資源所以要求權限驗證,還記得我們的用戶表吧,查看用戶表輸入用戶信息查看結果:
輸入"webservices"與"webservices-pwd"的用戶信息:
提示了一個"403"錯誤,這是因為雖然用戶信息正確,但是"webservices"用戶的沒有"myeclipseWeb"權限。
這次輸入一個不存在的用戶信息:
這次獲得了一個"401"錯誤,這是登陸失敗的提示結果,這裡會因浏覽器的不同而需要不同次數的失敗登陸才會得到這個結果。
接下來輸入一個正確的用戶,並且擁有"webservices"權限的用戶信息:
點擊"確定",獲得如下結果:
可以看到,我們成功的訪問了受保護的資源。若要傳中文字,解決方案我已經在前面"配置Struts2"時介紹過了,需要修改Struts 2默認的編碼方式還需要修改頁面的編碼方式,都改為"GBK"。
原文鏈接:http://www.cnblogs.com/suxiaolei/archive/2011/11/02/2233601.Html