前言
之前公司作项目时就有接触过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配置相关参考