JSP安全


在JSP和servlet開發的應用程式中,Web開發人員可以使用幾種機制來保護應用程式。資源通過在應用程式部署描述符中標識它們並向其分配角色來以宣告方式進行保護。

有幾個級別的身份驗證可用,從使用識別符號和密碼的基本身份驗證到使用證書的複雜身份驗證。

基於角色的認證

servlet規範中的認證機制使用了一種稱為基於角色的安全性技術。這個做法是,不是在使用者級別限制資源,而是建立角色並通過角色限制資源。

可以在檔案tomcat-users.xml中定義不同的角色,tomcat-users.xml位於Tomcat的主目錄conf中。此檔案的範例如下所示 -

<?xml version = '1.0' encoding = 'utf-8'?>
<tomcat-users>
   <role rolename = "tomcat"/>
   <role rolename = "role1"/>
   <role rolename = "manager"/>
   <role rolename = "admin"/>
   <user username = "tomcat" password = "tomcat" roles = "tomcat"/>
   <user username = "role1" password = "tomcat" roles = "role1"/>
   <user username = "both" password = "tomcat" roles = "tomcat,role1"/>
   <user username = "admin" password = "secret" roles = "admin,manager"/>
</tomcat-users>

此檔案定義了使用者名,密碼和角色之間的簡單對映。請注意,給定的使用者可能有多個角色; 例如,username =「both」有兩個角色:「tomcat」角色和「role1」角色。

當確定並定義了不同的角色,就可以通過使用WEB-INF目錄中web.xml檔案中的<security-constraint>元素,將基於角色的安全限制放在不同的Web應用程式資源上。

以下是web.xml中的範例元素項 -

<web-app>
   ...
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>SecuredBookSite</web-resource-name>
         <url-pattern>/secured/*</url-pattern>
         <http-method>GET</http-method>
         <http-method>POST</http-method>
      </web-resource-collection>

      <auth-constraint>
         <description>
            Let only managers use this app
         </description>
         <role-name>manager</role-name>
      </auth-constraint>
   </security-constraint>

   <security-role>
      <role-name>manager</role-name>
   </security-role>

   <login-config>
      <auth-method>BASIC</auth-method>
   </login-config>
   ...
</web-app>

以上元素項將意味著 -

  • 對與/secured/*匹配的URL的任何HTTP GET或POST請求將受到安全限制。
  • 具有manager角色的人員可獲得安全資源。
  • login-config元素用於描述BASIC認證形式。

如果嘗試瀏覽包含/security目錄的任何URL,將顯示以下對話方塊,要求輸入使用者名和密碼。 如果提供了使用者:admin和密碼:secrer,那麼可以存取與/secured/*匹配的URL,因為我們已將使用者管理員定義為允許存取該資源的manager角色。

基於表單的認證

使用表單身份驗證方法時,必須提供登入表單以提示使用者輸入使用者名和密碼。 以下是login.jsp的簡單程式碼。 這有助於為同一目的建立一個表單 -

<html>
   <body bgcolor = "#ffffff">

      <form method = "POST" action ="j_security_check">
         <table border = "0">
            <tr>
               <td>Login</td>
               <td><input type = "text" name="j_username"></td>
            </tr>
            <tr>
               <td>Password</td>
               <td><input type = "password" name="j_password"></td>
            </tr>
         </table>
         <input type = "submit" value = "Login!">

      </form>

   </body>
</html>

在這裡,必須確保登入表單中有包含名為:j_usernamej_password的表單元素。 <form>標籤中的操作必須是j_security_check。必須用作表單方法: POST。 同時,還需要修改<login-config>標籤,將auth-method指定為FORM -

<web-app>
   ...
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>SecuredBookSite</web-resource-name>
         <url-pattern>/secured/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
      </web-resource-collection>

      <auth-constraint>
         <description>Let only managers use this app</description>
         <role-name>manager</role-name>
      </auth-constraint>
   </security-constraint>

   <security-role>
      <role-name>manager</role-name>
   </security-role>

   <login-config>
      <auth-method>FORM</auth-method>
      <form-login-config>
         <form-login-page>/login.jsp</form-login-page>
         <form-error-page>/error.jsp</form-error-page>
      </form-login-config>
   </login-config>
   ...
</web-app>

現在當嘗試存取URL /secured/*任何資源時,將顯示上述表單,詢問使用者ID和密碼。 當容器看到j_security_check操作時,它使用一些內部機制來認證呼叫者。

如果登入成功並且呼叫者被授權存取受保護的資源,則容器使用對談ID從該點起為呼叫者標識登入對談。容器使用包含session-id的cookie維護登入對談。 伺服器將cookie傳送回用戶端,只要主呼叫方後續請求者提供該cookie,容器將知道呼叫者是誰。

如果登入失敗,則伺服器返回通過表單錯誤頁面設定標識的頁面

這裡,j_security_check是使用表單登入的應用程式必須為登入表單指定的操作。 同樣的形式,還應該有一個名為j_username的文字輸入控制元件和一個名為j_password的密碼輸入控制元件。當看到這個,這意味著表單中包含的資訊將被提交到伺服器,這將檢查名稱和密碼。 這是如何完成的是伺服器特定的。

檢查標準領域實現,以了解j_security_check如何用於Tomcat容器。

Servlet/JSP中的程式安全性

HttpServletRequest物件提供以下方法,可用於在執行時挖掘安全資訊 -

編號 方法 描述
1 String getAuthType() getAuthType()方法返回一個String物件,該物件表示用於保護Servlet的認證方案的名稱。
2 boolean isUserInRole(java.lang.String role) isUserInRole()方法返回一個布林值:如果使用者處於給定角色,則返回true,否則返回false
3 String getProtocol() getProtocol()方法返回一個String物件,表示用於傳送請求的協定。可以檢查該值以確定是否使用安全協定。
4 boolean isSecure() isSecure()方法返回一個布林值,表示是否使用HTTPS進行請求。值設定為true意味著它是和連線是安全的。 值設定為false表示請求不是安全的。
5 Principle getUserPrinciple() getUserPrinciple()方法返回一個java.security.Principle物件,該物件包含當前已驗證使用者的名稱。

例如,對於連結到管理員的頁面的JSP,可以使用以下程式碼 -

<% if (request.isUserInRole("manager")) { %>
   <a href = "managers/mgrreport.jsp">Manager Report</a>
   <a href = "managers/personnel.jsp">Personnel Records</a>
<% } %>

通過檢查使用者在JSP或Servlet中的角色,可以自定義該頁面,僅向使用者顯示可以存取的專案。 如果需要在認證表單中輸入使用者名,可以在請求物件中呼叫getRemoteUser()方法。