鍍金池/ 教程/ Java/ 關于登錄
初體驗
權限鑒定基礎
Remember-Me 功能
匿名認證
intercept-url配置
認證簡介
退出登錄 logout
AuthenticationProvider
Filter
關于登錄
異常信息本地化
緩存 UserDetails
session 管理
核心類簡介

關于登錄

form-login 元素介紹

http 元素下的 form-login 元素是用來定義表單登錄信息的。當我們什么屬性都不指定的時候 Spring Security 會為我們生成一個默認的登錄頁面。如果不想使用默認的登錄頁面,我們可以指定自己的登錄頁面。

使用自定義登錄頁面

自定義登錄頁面是通過 login-page 屬性來指定的。提到 login-page 我們不得不提另外幾個屬性。

  • username-parameter:表示登錄時用戶名使用的是哪個參數(shù),默認是 “j_username”。
  • password-parameter:表示登錄時密碼使用的是哪個參數(shù),默認是 “j_password”。
  • login-processing-url:表示登錄時提交的地址,默認是 “/j-spring-security-check”。這個只是 Spring Security 用來標記登錄頁面使用的提交地址,真正關于登錄這個請求是不需要用戶自己處理的。

所以,我們可以通過如下定義使 Spring Security 在需要用戶登錄時跳轉到我們自定義的登錄頁面。

   <security:http auto-config="true">
      <security:form-login login-page="/login.jsp"
         login-processing-url="/login.do" username-parameter="username"
         password-parameter="password" />
      <!-- 表示匿名用戶可以訪問 -->
      <security:intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
      <security:intercept-url pattern="/**" access="ROLE_USER" />
   </security:http>

需要注意的是,我們之前配置的是所有的請求都需要 ROLE_USER 權限,這意味著我們自定義的 “/login.jsp” 也需要該權限,這樣就會形成一個死循環(huán)了。解決辦法是我們需要給 “/login.jsp” 放行。通過指定 “/login.jsp” 的訪問權限為 “IS_AUTHENTICATED_ANONYMOUSLY” 或 “ROLE_ANONYMOUS” 可以達到這一效果。此外,我們也可以通過指定一個 http 元素的安全性為 none 來達到相同的效果。如:

   <security:http security="none" pattern="/login.jsp" />
   <security:http auto-config="true">
      <security:form-login login-page="/login.jsp"
         login-processing-url="/login.do" username-parameter="username"
         password-parameter="password" />
      <security:intercept-url pattern="/**" access="ROLE_USER" />
   </security:http>

它們兩者的區(qū)別是前者將進入 Spring Security 定義的一系列用于安全控制的 filter,而后者不會。當指定一個 http 元素的 security 屬性為 none 時,表示其對應 pattern 的 filter 鏈為空。從 3.1 開始,Spring Security 允許我們定義多個 http 元素以滿足針對不同的 pattern 請求使用不能的 filter 鏈。當為指定 pattern 屬性時表示對應的 http 元素定義將對所有的請求發(fā)生作用。

根據(jù)上面的配置,我們自定義的登錄頁面的內容應該是這樣子的:

   <form action="login.do" method="post">
      <table>
         <tr>
            <td> 用戶名:</td>
            <td><input type="text" name="username"/></td>
         </tr>
         <tr>
            <td> 密碼:</td>
            <td><input type="password" name="password"/></td>
         </tr>
         <tr>
            <td colspan="2" align="center">
                <input type="submit" value=" 登錄 "/>
                <input type="reset" value=" 重置 "/>
            </td>
         </tr>
      </table>
   </form>

指定登錄后的頁面

通過 default-target-url 指定

默認情況下,我們在登錄成功后會返回到原本受限制的頁面。但如果用戶是直接請求登錄頁面,登錄成功后應該跳轉到哪里呢?默認情況下它會跳轉到當前應用的根路徑,即歡迎頁面。通過指定 form-login 元素的 default-target-url 屬性,我們可以讓用戶在直接登錄后跳轉到指定的頁面。如果想讓用戶不管是直接請求登錄頁面,還是通過 Spring Security 引導過來的,登錄之后都跳轉到指定的頁面,我們可以通過指定 form-login 元素的 always-use-default-target 屬性為 true 來達到這一效果。

通過 authentication-success-handler-ref 指定

authentication-success-handler-ref 對應一個 AuthencticationSuccessHandler 實現(xiàn)類的引用。如果指定了 authentication-success-handler-ref,登錄認證成功后會調用指定 AuthenticationSuccessHandler 的 onAuthenticationSuccess 方法。我們需要在該方法體內對認證成功做一個處理,然后返回對應的認證成功頁面。使用了 authentication-success-handler-ref 之后認證成功后的處理就由指定的 AuthenticationSuccessHandler 來處理,之前的那些 default-target-url 之類的就都不起作用了。

以下是自定義的一個 AuthenticationSuccessHandler 的實現(xiàn)類。

publicclass AuthenticationSuccessHandlerImpl implements
      AuthenticationSuccessHandler {

   publicvoid onAuthenticationSuccess(HttpServletRequest request,
         HttpServletResponse response, Authentication authentication)
         throws IOException, ServletException {
      response.sendRedirect(request.getContextPath());
   }

}

其對應使用 authentication-success-handler-ref 屬性的配置是這樣的:

   <security:http auto-config="true">
      <security:form-login login-page="/login.jsp"
         login-processing-url="/login.do" username-parameter="username"
         password-parameter="password"
         authentication-success-handler-ref="authSuccess"/>
      <!-- 表示匿名用戶可以訪問 -->
      <security:intercept-url pattern="/login.jsp"
         access="IS_AUTHENTICATED_ANONYMOUSLY" />
      <security:intercept-url pattern="/**" access="ROLE_USER" />
   </security:http>
   <!-- 認證成功后的處理類 -->
   <bean id="authSuccess" class="com.xxx.AuthenticationSuccessHandlerImpl"/>

指定登錄失敗后的頁面

除了可以指定登錄認證成功后的頁面和對應的 AuthenticationSuccessHandler 之外,form-login 同樣允許我們指定認證失敗后的頁面和對應認證失敗后的處理器 AuthenticationFailureHandler。

通過 authentication-failure-url 指定

默認情況下登錄失敗后會返回登錄頁面,我們也可以通過 form-login 元素的 authentication-failure-url 來指定登錄失敗后的頁面。需要注意的是登錄失敗后的頁面跟登錄頁面一樣也是需要配置成在未登錄的情況下可以訪問,否則登錄失敗后請求失敗頁面時又會被 Spring Security 重定向到登錄頁面。

   <security:http auto-config="true">
      <security:form-login login-page="/login.jsp"
         login-processing-url="/login.do" username-parameter="username"
         password-parameter="password"
         authentication-failure-url="/login_failure.jsp"
         />
      <!-- 表示匿名用戶可以訪問 -->
      <security:intercept-url pattern="/login*.jsp*"
         access="IS_AUTHENTICATED_ANONYMOUSLY" />
      <security:intercept-url pattern="/**" access="ROLE_USER" />
   </security:http>

通過 authentication-failure-handler-ref 指定

類似于 authentication-success-handler-ref,authentication-failure-handler-ref 對應一個用于處理認證失敗的 AuthenticationFailureHandler 實現(xiàn)類。指定了該屬性,Spring Security 在認證失敗后會調用指定 AuthenticationFailureHandler 的 onAuthenticationFailure 方法對認證失敗進行處理,此時 authentication-failure-url 屬性將不再發(fā)生作用。

http-basic

之前介紹的都是基于 form-login 的表單登錄,其實 Spring Security 還支持彈窗進行認證。通過定義 http 元素下的 http-basic 元素可以達到這一效果。

   <security:http auto-config="true">
      <security:http-basic/>
      <security:intercept-url pattern="/**" access="ROLE_USER" />
   </security:http>

此時,如果我們訪問受 Spring Security 保護的資源時,系統(tǒng)將會彈出一個窗口來要求我們進行登錄認證。效果如下:

http://wiki.jikexueyuan.com/project/spring-security/images/2.png" alt="" />

當然此時我們的表單登錄也還是可以使用的,只不過當我們訪問受包含資源的時候 Spring Security 不會自動跳轉到登錄頁面。這就需要我們自己去請求登錄頁面進行登錄。

需要注意的是當我們同時定義了 http-basic 和 form-login 元素時,form-login 將具有更高的優(yōu)先級。即在需要認證的時候 Spring Security 將引導我們到登錄頁面,而不是彈出一個窗口。