Spring Security 自己的UsernamePasswordAuthenticationFilter 只支持 帳號與密碼的驗證,若是須要加入諸如驗證碼等其它條件時,能夠經過繼承UsernamePasswordAuthenticationFilter 並重寫其中的方法 attemptAuthentication來實現。java
java代碼以下web
public class ValidateCodeFilter extends UsernamePasswordAuthenticationFilter { @Override public Authentication attemptAuthentication(final HttpServletRequest request, final HttpServletResponse response) throws AuthenticationException { String validateCode = request.getParameter("validateCode"); if (validateCode == null) { validateCode = ""; } final String validation_code = (String) request.getSession().getAttribute("validation_code"); logger.info("開始校驗驗證碼,生成的驗證碼爲:" + validation_code + " ,輸入的驗證碼爲:" + validateCode); if (!validateCode.equals(validation_code)) { throw new LockedException("text.login.username.notexist"); } return super.attemptAuthentication(request, response); } }
spring-security-config.xml 配置以下spring
<!-- validate filter --> <bean id="validateFilter" class="com.java.filters.ValidateCodeFilter"> <property name="authenticationManager" ref="authenticationManager"></property> <property name="authenticationSuccessHandler" ref="loginAuthenticationSuccessHandler"> </property> <property name="authenticationFailureHandler" ref="loginAuthenticationFailureHandler"> </property> </bean>
<!-- Default security config --> <security:http request-matcher-ref="excludeUrlRequestMatcher" entry-point-ref="loginEntryPoint" auto-config="false"> <security:anonymous username="anonymous" granted-authority="ROLE_ANONYMOUS" /> <security:access-denied-handler error-page="/login"/> <security:session-management session-authentication-strategy-ref="fixation" /> <security:csrf token-repository-ref="csrfTokenRepository" request-matcher-ref="csrfProtectionMatcher" /> <security:custom-filter before="CSRF_FILTER" ref="logoutFilter" /> <!-- 替代原生的驗證 --> <security:custom-filter position="FORM_LOGIN_FILTER" ref="customLoginFilter" /> <!-- RememberMe --> <security:remember-me key="jahwastorefront" services-ref="rememberMeServices" /> <!-- SSL / AUTHENTICATED pages --> <security:intercept-url pattern="/my-account/addressform" access="hasAnyRole('ROLE_ANONYMOUS','ROLE_CUSTOMERGROUP')" requires-channel="https" /> <security:intercept-url pattern="/checkout/multi/billingaddressform" access="hasAnyRole('ROLE_ANONYMOUS','ROLE_CUSTOMERGROUP')" requires-channel="https" /> <security:intercept-url pattern="/my-account*" access="hasRole('ROLE_CUSTOMERGROUP')" requires-channel="https" /> <security:intercept-url pattern="/my-account/order/*/getReadOnlyProductVariantMatrix" access="hasAnyRole('ROLE_ANONYMOUS','ROLE_CUSTOMERGROUP')" requires-channel="https" /> <security:intercept-url pattern="/my-account/**" access="hasRole('ROLE_CUSTOMERGROUP')" requires-channel="https" /> <security:intercept-url pattern="/quote/**" access="hasRole('ROLE_CUSTOMERGROUP')" requires-channel="https" /> <security:intercept-url pattern="/**" requires-channel="https" /> <!-- Everything should be secure --> <!-- 這個地方必定要註釋掉 <security:form-login login-page="/login" authentication-failure-handler-ref="loginAuthenticationFailureHandler" authentication-success-handler-ref="loginGuidAuthenticationSuccessHandler" username-parameter="j_username" password-parameter="j_password" login-processing-url="/j_spring_security_check" /> -->
<!-- loginEntryPoint --> <bean id="loginEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <!-- 默認登陸頁的url --> <constructor-arg value="/login" /> </bean>
另一定要注意 配置 auto-config="false",否則會報以下的錯誤session
nested exception is org.springframework.beans.factory.parsing.BeanDefinitionParsingException:
Configuration problem: Filter beans '<validateFilter>' and '<org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0>' have the same 'order' value.
When using custom filters, please make sure the positions do not conflict with default filters.
Alternatively you can disable the default filters by removing the corresponding child elements from <http> and avoiding the use of <http auto-config='true'>.