淺談spring security 403機制
403就是access denied ,就是請求拒絕,因為許可權不足
三種許可權級別
一、無許可權訪問
<security:http security="none" pattern="/index.jsp" />
這種即是不需要登入,也可以訪問的,但是不會傳csrf_key
二、匿名訪問
<security:http>
<security:intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
</security:http>
這種也是不需要登入就訪問的,但是會傳csrf_key
三、有許可權訪問
<security:http>
<security:intercept-url pattern="/index.jsp" access="xxxxx"/>
</security:http>
這種就需要使用者登入了,而且需要相應的許可權才能訪問,不然就報403(access denied)
沒有跳轉403?
今天遇到了一個詭異的問題
admin.jsp設定為access="USER",需要使用者登入了,而且需要有USER許可權才能訪問
然而我沒登陸的時候,去訪問admin.jsp,結果沒有跳到403頁面,跳到了login.jsp
在我預想的是,跳到403
原因
當用戶已經登入了,但是許可權不足,才會跳轉到403
當用戶沒有登入的時候,訪問有許可權的頁面,只會跳轉到登陸頁面
機制
spring security處理請求的時候,先會檢測使用者是否登入,也就是檢測是否有authentication(身份)
此時,如果使用者沒有登入,而且請求是需要登入的action,spring security會跳轉到登陸頁面,就算這個頁面需要許可權訪問,也不會出現403。
登入的時候,會在SecurityContextHolder裡面放一個記錄使用者資訊(使用者名稱、許可權)的principal,需要驗證使用者許可權的時候,就會從SecurityContextHolder取出principal來驗證許可權。
如果使用者已經登入了(有了authentication),如果使用者的許可權不足,就會報403 這個時候security:access-denied-handler才會生效
自定義403
想要自定義403,需要在spring-security.xml裡面設定security:access-denied-handler
有兩種方式:
指定AccessDeniedHandler
自定義一個403處理機制,需要實現AccessDeniedHandler介面,實現裡面的handle方法
當權限不足的時候,spring security會呼叫handle方法
可以在handle方法裡面重定向或者轉發請求
程式碼demo
public class AccessDeniedServletHandler implements AccessDeniedHandler { private static final String DEF_ERROR_PAGE_PATH="action/deniedServlet_denied"; @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { response.sendRedirect(DEF_ERROR_PAGE_PATH); } }
在spring-security.xml配置
<security:access-denied-handler ref="accessDeniedServletHandler" />
<bean id="accessDeniedServletHandler" class="com.xxx.servlet.AccessDeniedServletHandler" scope="singleton"></bean>
指定error-page
這種方式,實際上是轉發請求,做不到重定向
在spring-security.xml配置
<security:access-denied-handler error-page="403.html" />
整合Struts的問題
情景
前提:自定義的403頁面的URL,是通過struts的action訪問的
當權限不足的時候,將請求轉發到自定義的403頁面時,會出現404( not found)
但是直接訪問403頁面的時候,又是正常的
原因
所以推測
spring security 的DefaultSecurityFilterChain在strust的filter之後
所以struts捕獲不到請求的403頁面,但是請求方式又是action,所以就找不到頁面了
結論
所以這樣子的話,一切spring security 處理完成後自定義跳轉,都是在strust的filter之後的
像登入成功的authentication-success-handler-ref,退出的success-handler-ref以及access denied的security:access-denied-handler
所以訪問action的小心的,要用重定向的方式
檢視原文:http://139.129.55.235/2016/06/01/%e6%b5%85%e8%b0%88spring-security-403%e6%9c%ba%e5%88%b6/