前言
之前公司作項目時就有接觸過spring security,不過是由他人搭建起來,自己在其基礎實現如單點登陸,輸入錯誤限制等一些小功能。感覺自己對該框架的理解不是很深,於是花了一些時間重新搭建spring security框架,整理成文檔,希望能夠幫到有需要的人。
環境配置
- IDE工具:IDEA-2017.1
- 系統環境:win10 tomcat-9.0.0.1 java-1.8 mysql-5.7
- spring-security版本:4.2.2
實現功能
實現用戶登錄時,驗證其合法性,並通過security訪問數據庫可以獲取到相對應角色和資源信息存儲到SecurityContext裏面。
具體流程
- 1.tomcat啓動時:調用【CustomInvocationSecurityMetadataSource】進行初始化角色權限和資源【initResources】
- 2.用戶發出請求
- 3.【securityFilter】攔截並判斷
- 4.【CustomInvocationSecurityMetadataSource:getAttributes】取得請求資源所需權限
- 5.用戶點擊【登陸】
- 6.訪問登陸攔截器【loginFilter】
- 7.跳到【CustomUserDetailsService:loadUserByUsername】根據用戶加載相對應的資源
- 8.跳到自定義密碼處理類【CustomPasswordEncoder】,驗證密碼是否對錯。
- 9.如果出錯,跳到相對應的登陸錯誤頁面。正確則跳到成功頁面
具體配置
- 1.在pom.xml中引入所需的jar包
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
- 2.在web.xml配置SpringSecurity處理的請求的攔截器
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springCharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.spring-security.xml具體配置
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- @描述:
1、儘量避免使用auto-config="true"這是個自動配置過濾器(Filter)的屬性,這個可以幫我們自動配置login form以及相關配置,默認值是false
2、use-expressions如果開啓,則允許使用spring的EL表達式,例如<intercept-url pattern="/*" access="hasRole('ROLE_USER')"/> -->
<http entry-point-ref="myAuthenticationEntryPoint" use-expressions="true">
<!-- @描述:登出後刪除cookie -->
<logout delete-cookies="JSESSIONID"/>
<!-- 登錄過濾器 -->
<custom-filter before="FORM_LOGIN_FILTER" ref="loginFilter"/>
<!-- @描述:權限攔截器 -->
<custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="securityFilter"/>
<csrf disabled="true"/>
<!-- @描述:session管理 -->
<session-management invalid-session-url="/loginFailure.page">
<concurrency-control max-sessions="1" expired-url="/loginFailure.page" />
</session-management>
</http>
<!-- @描述:配置auto_config=false,必須設置一個入口點,僅僅是被ExceptionTranslationFilter引用的,
是在出現認證異常、訪問異常時,通過入口點決定redirect、forward的操作,用來經過ExceptionTranslationFilter過濾器處理後,
先捕獲到訪問拒絕異常,並把跳轉動作交給入口點來處理 -->
<beans:bean id="myAuthenticationEntryPoint" class="com.demo.base.security.CustomAuthenticationEntryPoint">
<beans:constructor-arg name="loginFormUrl" value="/index.page"/>
</beans:bean>
<!-- 登陸過濾器 -->
<beans:bean id="loginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="authenticationFailureHandler" ref="failureHandler"/>
<beans:property name="authenticationSuccessHandler" ref="successHandler"/>
<beans:property name="filterProcessesUrl" value="/login.ajax"/>
</beans:bean>
<!-- @描述:權限過濾器 -->
<beans:bean id="securityFilter" class="com.demo.base.security.CustomSecurityInterceptor">
<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource"/>
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="accessDecisionManager" ref="myAccessDecisionManagerBean"/>
</beans:bean>
<!-- @描述:失敗處理類 -->
<beans:bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/loginFailure.page"/>
</beans:bean>
<!-- @描述:成功處理類 -->
<beans:bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
<beans:property name="defaultTargetUrl" value="/loginSuccess.page"/>
</beans:bean>
<!-- 權限鑑定管理類 -->
<authentication-manager alias="authenticationManager">
<authentication-provider ref="authenticationProvider"/>
</authentication-manager>
<beans:bean id="authenticationProvider"
class="com.demo.base.security.CustomAuthenticationProvider">
<beans:property name="userDetailsService" ref="customUserDetailsService"/>
<beans:property name="hideUserNotFoundExceptions" value="false"/>
<beans:property name="passwordEncoder" ref="passwordEncoder"/>
</beans:bean>
<!-- @描述:自定義密碼驗證類 -->
<beans:bean id="passwordEncoder" class="com.demo.base.security.CustomPasswordEncoder"/>
<!-- 通過 customUserDetailsService,Spring會控制用戶的訪問級別.
也可以理解成:以後我們和數據庫操作就是通過customUserDetailsService來進行關聯. -->
<beans:bean id="customUserDetailsService" class="com.demo.base.security.CustomUserDetailsService"/>
<!-- 獲取數據庫中所有的url資源,讀出url資源與權限的對應關係 -->
<beans:bean id="mySecurityMetadataSource"
class="com.demo.base.security.CustomInvocationSecurityMetadataSource">
<beans:constructor-arg name="securityService" ref="sysRoleResourceLogService"/>
</beans:bean>
<!-- 判斷是否有權限訪問請求的url頁面 -->
<beans:bean id="myAccessDecisionManagerBean" class="com.demo.base.security.CustomAccessDecisionManager"/>
</beans:beans>
相關參考博客
- entry-point-ref參數解釋
- auto-config用法
- spring-security use-expressions詳解
- spring secuirty中文API文檔
- SpringSecurity配置相關參考