Spring Security3.1登錄驗證

1、前言php

      在上一篇http://blog.csdn.net/k10509806/archive/2011/04/28/6369131.aspx文章中,提到的MyUserDetailServiceImpl獲取用戶權限,在用戶沒有登錄的時候,Spring Security會讓咱們自動跳轉到默認的登錄界面,但在實際應用絕大多數是用咱們本身的登錄界面的,其中就包括一些咱們本身的邏輯,好比驗證碼。因此本人又研究一下,終於摸清了一些如何配置本身的登錄界面的辦法。在這裏獻醜了。html

 

2、Spring Security的過濾器java

      經過DEBUG能夠看到Spring Security的Filter的順序web

Security filter chain: [
  ConcurrentSessionFilter
  SecurityContextPersistenceFilter
  LogoutFilter
  MyUsernamePasswordAuthenticationFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  RememberMeAuthenticationFilter
  AnonymousAuthenticationFilter
  SessionManagementFilter
  ExceptionTranslationFilter
  MySecurityFilter
  FilterSecurityInterceptor
]
spring

Spring Security的登錄驗證用的就是MyUsernamePasswordAuthenticationFilter,因此要實現咱們本身的驗證,能夠寫一個類並繼承MyUsernamePasswordAuthenticationFilter類,重寫attemptAuthentication方法。express

 

3、applicationContext-Security.xml配置apache

[xhtml] view plaincopysession

  1. <?xml version="1.0" encoding="UTF-8"?>  app

  2. <beans:beans xmlns="http://www.springframework.org/schema/security"  jsp

  3.     xmlns:beans="http://www.springframework.org/schema/beans"  

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

  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  

  6.                         http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">  

  7.                           

  8.     <debug/>        

  9.     <http pattern="/js/**" security="none"/>  

  10.     <http pattern="/resource/**" security="none"></http>  

  11.     <http pattern="/login.jsp" security="none"/>  

  12.       

  13.     <http use-expressions="true" entry-point-ref="authenticationProcessingFilterEntryPoint">  

  14.         <logout/>  

  15.         <!-- 實現免登錄驗證 -->  

  16.         <remember-me />  

  17.         <session-management invalid-session-url="/timeout.jsp">  

  18.             <concurrency-control max-sessions="10" error-if-maximum-exceeded="true" />  

  19.         </session-management>  

  20.           

  21.         <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER"  />  

  22.         <custom-filter ref="securityFilter" before="FILTER_SECURITY_INTERCEPTOR"/>  

  23.     </http>  

  24.       

  25.     <!-- 登陸驗證器 -->  

  26.     <beans:bean id="loginFilter"  

  27.         class="com.huaxin.security.MyUsernamePasswordAuthenticationFilter">  

  28.         <!-- 處理登陸的action -->  

  29.         <beans:property name="filterProcessesUrl" value="/j_spring_security_check"></beans:property>  

  30.                 <!-- 驗證成功後的處理-->  

  31.         <beans:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"></beans:property>  

  32.                 <!-- 驗證失敗後的處理-->  

  33.         <beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"></beans:property>  

  34.         <beans:property name="authenticationManager" ref="myAuthenticationManager"></beans:property>  

  35.         <!-- 注入DAO爲了查詢相應的用戶 -->  

  36.         <beans:property name="usersDao" ref="usersDao"></beans:property>  

  37.     </beans:bean>  

  38.     <beans:bean id="loginLogAuthenticationSuccessHandler"  

  39.         class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">  

  40.         <beans:property name="defaultTargetUrl" value="/index.jsp"></beans:property>  

  41.     </beans:bean>  

  42.     <beans:bean id="simpleUrlAuthenticationFailureHandler"  

  43.         class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">  

  44.         <!-- 能夠配置相應的跳轉方式。屬性forwardToDestination爲true採用forward false爲sendRedirect -->  

  45.         <beans:property name="defaultFailureUrl" value="/login.jsp"></beans:property>  

  46.     </beans:bean>  

  47.       

  48.     <!-- 認證過濾器 -->  

  49.     <beans:bean id="securityFilter" class="com.huaxin.security.MySecurityFilter">  

  50.         <!-- 用戶擁有的權限 -->  

  51.         <beans:property name="authenticationManager" ref="myAuthenticationManager" />  

  52.         <!-- 用戶是否擁有所請求資源的權限 -->  

  53.         <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />  

  54.         <!-- 資源與權限對應關係 -->  

  55.         <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />  

  56.     </beans:bean>  

  57.     <!-- 實現了UserDetailsService的Bean -->  

  58.     <authentication-manager alias="myAuthenticationManager">  

  59.         <authentication-provider user-service-ref="myUserDetailServiceImpl" />  

  60.     </authentication-manager>  

  61.       

  62.     <beans:bean id="myAccessDecisionManager" class="com.huaxin.security.MyAccessDecisionManager"></beans:bean>  

  63.     <beans:bean id="mySecurityMetadataSource" class="com.huaxin.security.MySecurityMetadataSource">  

  64.         <beans:constructor-arg name="resourcesDao" ref="resourcesDao"></beans:constructor-arg>  

  65.     </beans:bean>  

  66.     <beans:bean id="myUserDetailServiceImpl" class="com.huaxin.security.MyUserDetailServiceImpl">  

  67.         <beans:property name="usersDao" ref="usersDao"></beans:property>  

  68.     </beans:bean>  

  69.       

  70.     <!-- 未登陸的切入點 -->  

  71.     <beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">  

  72.         <beans:property name="loginFormUrl" value="/login.jsp"></beans:property>  

  73.     </beans:bean>  

  74. </beans:beans>  

這裏特別要說明一下,咱們的<http>標籤不能配置auto-config,由於這樣配置後,依然會採用Spring Security的Filter Chain會與下面咱們配的custom-filter衝突,最好會拋異常。還有配置一個切入點entry-point-ref="authenticationProcessingFilterEntryPoint",爲了在未登錄的時候,跳轉到哪一個頁面,不配也會拋異常。

 <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER"  /> position表示替換掉Spring Security原來默認的登錄驗證Filter。

 

4、MyUsernamePasswordAuthenticationFilter

[java] view plaincopy

  1. package com.huaxin.security;  

  2.   

  3. import javax.servlet.http.HttpServletRequest;  

  4. import javax.servlet.http.HttpServletResponse;  

  5. import javax.servlet.http.HttpSession;  

  6.   

  7. import org.apache.commons.lang.xwork.StringUtils;  

  8. import org.springframework.security.authentication.AuthenticationServiceException;  

  9. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;  

  10. import org.springframework.security.core.Authentication;  

  11. import org.springframework.security.core.AuthenticationException;  

  12. import org.springframework.security.web.WebAttributes;  

  13. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;  

  14.   

  15. import com.huaxin.bean.Users;  

  16. import com.huaxin.dao.UsersDao;  

  17.   

  18. /* 

  19.  *  

  20.  * UsernamePasswordAuthenticationFilter源碼 

  21.     attemptAuthentication 

  22.         this.getAuthenticationManager() 

  23.             ProviderManager.java 

  24.                 authenticate(UsernamePasswordAuthenticationToken authRequest) 

  25.                     AbstractUserDetailsAuthenticationProvider.java 

  26.                         authenticate(Authentication authentication) 

  27.                             P155 user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); 

  28.                                 DaoAuthenticationProvider.java 

  29.                                     P86 loadUserByUsername 

  30.  */  

  31. public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{  

  32.     public static final String VALIDATE_CODE = "validateCode";  

  33.     public static final String USERNAME = "username";  

  34.     public static final String PASSWORD = "password";  

  35.       

  36.     private UsersDao usersDao;  

  37.     public UsersDao getUsersDao() {  

  38.         return usersDao;  

  39.     }  

  40.     public void setUsersDao(UsersDao usersDao) {  

  41.         this.usersDao = usersDao;  

  42.     }  

  43.   

  44.     @Override  

  45.     public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {  

  46.         if (!request.getMethod().equals("POST")) {  

  47.             throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());  

  48.         }  

  49.         //檢測驗證碼  

  50.         checkValidateCode(request);  

  51.           

  52.         String username = obtainUsername(request);  

  53.         String password = obtainPassword(request);  

  54.           

  55.         //驗證用戶帳號與密碼是否對應  

  56.         username = username.trim();  

  57.           

  58.         Users users = this.usersDao.findByName(username);  

  59.           

  60.         if(users == null || !users.getPassword().equals(password)) {  

  61.     /* 

  62.               在咱們配置的simpleUrlAuthenticationFailureHandler處理登陸失敗的處理類在這麼一段 

  63.         這樣咱們能夠在登陸失敗後,向用戶提供相應的信息。 

  64.         if (forwardToDestination) { 

  65.             request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); 

  66.         } else { 

  67.             HttpSession session = request.getSession(false); 

  68.  

  69.             if (session != null || allowSessionCreation) { 

  70.                 request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); 

  71.             } 

  72.         } 

  73.      */  

  74.             throw new AuthenticationServiceException("用戶名或者密碼錯誤!");   

  75.         }  

  76.           

  77.         //UsernamePasswordAuthenticationToken實現 Authentication  

  78.         UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);  

  79.         // Place the last username attempted into HttpSession for views  

  80.           

  81.         // 容許子類設置詳細屬性  

  82.         setDetails(request, authRequest);  

  83.           

  84.         // 運行UserDetailsService的loadUserByUsername 再次封裝Authentication  

  85.         return this.getAuthenticationManager().authenticate(authRequest);  

  86.     }  

  87.       

  88.     protected void checkValidateCode(HttpServletRequest request) {   

  89.         HttpSession session = request.getSession();  

  90.           

  91.         String sessionValidateCode = obtainSessionValidateCode(session);   

  92.         //讓上一次的驗證碼失效  

  93.         session.setAttribute(VALIDATE_CODE, null);  

  94.         String validateCodeParameter = obtainValidateCodeParameter(request);    

  95.         if (StringUtils.isEmpty(validateCodeParameter) || !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {    

  96.             throw new AuthenticationServiceException("驗證碼錯誤!");    

  97.         }    

  98.     }  

  99.       

  100.     private String obtainValidateCodeParameter(HttpServletRequest request) {  

  101.         Object obj = request.getParameter(VALIDATE_CODE);  

  102.         return null == obj ? "" : obj.toString();  

  103.     }  

  104.   

  105.     protected String obtainSessionValidateCode(HttpSession session) {  

  106.         Object obj = session.getAttribute(VALIDATE_CODE);  

  107.         return null == obj ? "" : obj.toString();  

  108.     }  

  109.   

  110.     @Override  

  111.     protected String obtainUsername(HttpServletRequest request) {  

  112.         Object obj = request.getParameter(USERNAME);  

  113.         return null == obj ? "" : obj.toString();  

  114.     }  

  115.   

  116.     @Override  

  117.     protected String obtainPassword(HttpServletRequest request) {  

  118.         Object obj = request.getParameter(PASSWORD);  

  119.         return null == obj ? "" : obj.toString();  

  120.     }  

  121.       

  122.       

  123. }  

有時間,你們看看源碼吧。

 

5、login.jsp

[php] view plaincopy

  1. <body>  

  2.   <span style="color:red"><%=session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) %></span>  

  3.    <form action="j_spring_security_check" method="post">  

  4.     Account:<Input name="username"/><br/>  

  5.     Password:<input name="password" type="password"/><br/>  

  6.     <input value="submit" type="submit"/>  

  7.    </form>  

  8.  </body>  

相關文章
相關標籤/搜索