某天,你的客戶提出這樣一個需求,在點擊購買商品的時,若是用戶沒有註冊,而且用戶沒有帳號,這時用戶去建立帳戶,而後要直接返回到想購買商品的付款頁面。你會該如何基於Spring Security實現?java
Spring Security 是爲基於Spring的應用程序提供聲明式安全保護的安全性框架。它可以在Web請求級別和方法調用級別處理身份驗證和受權。由於基於Spring框架,因此Spring Security充分利用依賴注入(dependency injection)和AOP.git
Spring Security提供了多種驗證方式,最多見的有:XML配置和數據庫驗證方式。試想當咱們點擊購買商品而且沒有登陸的狀況下,Spring Security 通常會跳到登陸,可是登錄是由Spring幫咱們實現的,因此咱們跳到登錄頁面後也就丟失了與商品的聯繫,其實這中間Spring會經歷多個步驟,最後幫你驗證你輸入的結果。在跳進登錄頁面前Spring會先調用默認 AuthenticationEntryPoint接口的方法,咱們經過重載這個方法能夠實現咱們想進行的操做,這裏就是保存用戶點擊的商品信息。github
1 public class SimpleEntryPointHandler implements AuthenticationEntryPoint { 2 3 @Override 4 public void commence(HttpServletRequest request, HttpServletResponse httpServletResponse, AuthenticationException e) throws ServletException { 5 if (request.getRequestURI().contains("/payment")) { 6 httpServletResponse.sendRedirect("/"); 7 } 8 else{ 9 request.getSession().setAttribute("reserveItemId", request.getParameter("itemId")); 10 httpServletResponse.sendRedirect("/login"); 11 } 12 } 13 }
spring-security部分配置: spring
1 <beans:bean id="simpleEntryPointHandler" class="com.trailblazers.freewheelers.security.SimpleEntryPointHandler"/> 2 3 <http auto-config="true" entry-point-ref="simpleEntryPointHandler"> 4 <intercept-url pattern="/admin" access="ROLE_ADMIN"/> 5 <intercept-url pattern="/item" access="ROLE_ADMIN"/> 6 <intercept-url pattern="/reserve" access="ROLE_ADMIN, ROLE_USER"/> 7 <intercept-url pattern="/deliveryAddress" access="ROLE_ADMIN, ROLE_USER"/> 8 <intercept-url pattern="/userProfile" access="ROLE_ADMIN, ROLE_USER"/> 9 <intercept-url pattern="/userProfile/**" access="ROLE_ADMIN"/> 10 <intercept-url pattern="/payment" access="ROLE_ADMIN,ROLE_USER"/> 11 <form-login login-page="/login" default-target-url="/userProfile" 12 authentication-failure-url="/loginfailed"/> 13 <logout logout-success-url="/" /> 14 <access-denied-handler error-page="/403" /> 15 </http>
解決了如何在login以前進行一些操做,接下來就是解決如何在建立用戶以後進行登錄。Spring Security的驗證是經過用戶實現AuthenticationManager接口裏的authenticate方法來驗證的,常見的驗證方法以前也提到了。因此當用戶填好數據跳轉到controller得時候咱們手動實現這個方法,就能手動操做spring security來幫咱們進行驗證,具體以下:數據庫
1 @Component 2 public class AutoLogin { 3 4 @Autowired 5 @Qualifier("authenticationManager") 6 protected AuthenticationManager authenticationManager; 7 8 public void autoLogin(Account account, HttpServletRequest request) { 9 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( 10 account.getEmailAddress(), account.getPassword()); 11 12 request.getSession(); 13 14 token.setDetails(new WebAuthenticationDetails(request)); 15 Authentication authenticatedUser = authenticationManager.authenticate(token); 16 17 SecurityContextHolder.getContext(). setAuthentication(authenticatedUser); 18 } 19 }
而後 Controller能夠裝配這個bean 調用authenticate就可達到登陸效果。編程
spring-security部分配置:安全
此配置也就是數據庫驗證的測試provider,它制定了spring security驗證手法,而且可以以bean的方式注入到java service裏面,使其變得更加靈活。框架
1 <authentication-manager alias="authenticationManager"> 2 <authentication-provider> 3 <jdbc-user-service data-source-ref="myDataSource" 4 users-by-username-query="select email_address, password, enabled from account where upper(email_address)=upper(?)" 5 authorities-by-username-query="select a.email_address, ar.role from account a, 6 account_role ar where a.account_name = ar.account_name and upper(a.email_address)=upper(?)" 7 /> 8 </authentication-provider> 9 </authentication-manager>
最後,本例子只是Spring Security中的一部分,Spring Security將系統安全邏輯從業務中分離出來,充分利用面向切面編程的思想,因此是一個值得深刻研究的框架。經過這個切入點咱們也能夠探尋spring security執行的整個流程,更瞭解它的精髓。ide
本例子代碼:https://github.com/yeahyangliu/spring-security.git測試