Spring Security入门一:基本配置及使用
一、简介
Spring Security是基于Spring Core的一个具体工具实现,主要用来管理应用程序的安全性,并提供了一组用户权限的解决方案。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC和AOP,为应用系统提供声明式的安全访问控制功能。同为安全框架的还有Apache Shiro,在了解Spring Security之后,我们可以做一个两者的比较。
二、配置及使用
1.在pom.xml文件中添加maven坐标:在此处使用Spring Security 3
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>3.2.0.REALEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.0.REALEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.0.REALEASE</version>
</dependency>
2.在web.xml中配置filter
<!-- Spring-security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--非必须项:sitemesh装饰器放在spring security过来器的后面,以免装饰器页中的security不起作用-->
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>
org.sitemesh.config.ConfigurableSiteMeshFilter
</filter-class>
<init-param>
<param-name>ignore</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意:filter-name必须为springSecurityFilterChain。在DelegatingFilterProxy类init时,会通过这个固定的filter-name,去Spring中获取代理的bean。
之外,如果配置了sitemesh装饰器,如果在装饰器页面中用到了security,比如标签,那么security过滤器需要配置在sitemesh之前,否则装饰器页中的<sec:authorize>标签可能不起作用。
(security的filter不影响springmvc/struts的filter的配置顺序)
sitemash(待补充)
在DelegatingFilterProxy的initFilterBean()进行filterBean的初始化,在doFilter()中二次判断filterBean是否为null,如果为null,再次初始化filterBean
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}
3.spring-security配置文件
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 不拦截资源,配置方式一 -->
<http pattern="/login.jsp" security="none"/>
<http pattern="/favicon.ico" security="none"/>
<!-- 需要权限的资源
use-expressions="true" : 表达式语言配置访问控制
entry-point-ref="****" : 设置第三方登录入口
-->
<http use-expressions="true" entry-point-ref="apiAccessSecurity">
<!-- 这是spring提供的http/https信道 -->
<!-- 释放公共资源,允许人和人访问,access中自定义的permitAll为不拦截 -->
<intercept-url pattern="/common/**" access="permitAll" />
<intercept-url pattern="/css/**" access="permitAll" />
<intercept-url pattern="/img**" access="permitAll" />
<intercept-url pattern="/images/**" access="permitAll" />
<intercept-url pattern="/js/**" access="permitAll" />
<intercept-url pattern="/fonts/**" access="permitAll" />
<intercept-url pattern="/style/**" access="permitAll" />
<intercept-url pattern="/login.jsp*" access="permitAll" />
<intercept-url pattern="/index.jsp*" access="permitAll" />
<!-- 配置用户正常访问page -->
<intercept-url pattern="/**" access="isAuthenticated()" />
<!-- 自定义用户登陆page default-target-url登陆成功跳转的page(可选配置,默认为web.xml中的欢迎页面),authentication-failure-url="/login.jsp?error=true"这里是登陆失败跳转的page(可选配置) -->
<form-login login-page="/login.jsp" default-target-url="/jsp/index/main.jsp" authentication-failure-url="/login.jsp?error=true"/>
<logout success-handler-ref="logoutSuccessHandler" />
<remember-me />
<session-management>
<concurrency-control max-sessions="1"
error-if-maximum-exceeded="false" />
</session-management>
<logout invalidate-session="true" logout-url="/logout" logout-success-url="/"/>
<custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER"/>
</http>
<authentication-manager>
<!--
authentication-provider
引用userDetailsService实现类时使用user-service-ref属性,
引用authentication实现类时使用ref属性
这两个属性的区别在于
ref:直接将ref依赖的bean注入到AuthenticationProvider的集合中
user-service-ref:定义DaoAuthenticationProvider的bean注入到AuthenticationProvider的providers集合中,并且DaoAuthenticationProvider的变量userDetailsService由user-service-ref依赖的bean注入
-->
<authentication-provider ref="myAuthenticationProvider">
</authentication-provider>
</authentication-manager>
<!-- 登出操作 -->
<beans:bean id="logoutSuccessHandler"
class="com.my.sys.authentication.LogoutSuccessHandler">
<beans:property name="loginLogService" ref="loginLogService"></beans:property>
</beans:bean>
<beans:bean id="myAuthenticationProvider"
class="com.my.sys.authentication.myAuthenticationProvider">
<beans:property name="myPasswordValidator" ref="myPasswordValidator"></beans:property>
<beans:property name="userDetailsService" ref="userDetailsService"></beans:property>
</beans:bean>
<beans:bean id="userDetailsService"
class="com.shangde.common.sys.authentication.my263UserDetailsService">
<beans:property name="myPasswordValidator" ref="myPasswordValidator"></beans:property>
<beans:property name="authManageService" ref="authorizationManageService" />
</beans:bean>
<!-- 注入AuthorizationManageServiceImpl -->
<beans:bean id="authorizationManageService"
class="com.shangde.common.sys.authorization.AuthorizationManageServiceImpl"
scope="prototype">
<beans:property name="dataSource" ref="dataSource_ent"></beans:property>
<beans:property name="myPasswordValidator" ref="myPasswordValidator"></beans:property>
<beans:property name="officeService" ref="officeService"></beans:property>
<beans:property name="systemParameterService" ref="sysParameterService"></beans:property>
</beans:bean>
<!-- -->
<beans:bean id="myPasswordValidator"
class="com.shangde.common.authentication.myPasswordValidatorImpl">
<beans:property name="domain" value="${domain}"></beans:property>
<beans:property name="account" value="${account}"></beans:property>
<beans:property name="key" value="${key}"></beans:property>
<beans:property name="webServiceUrl" value="${webServiceUrl}"></beans:property>
<beans:property name="ldapTemplate" ref="ldapTemplate" />
</beans:bean>
<beans:bean id="contextSource"
class="org.springframework.ldap.core.support.LdapContextSource">
<beans:property name="url" value="${ldap.url}" />
<beans:property name="base" value="dc=sunlands,dc=com" />
<beans:property name="userDn" value="cn=Manager,dc=sunlands,dc=com" />
<beans:property name="password" value="secret" />
</beans:bean>
<beans:bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<beans:constructor-arg ref="contextSource" />
</beans:bean>
<beans:bean class="com.my.auth.ApiAccessSecurity" name="apiAccessSecurity" id="apiAccessSecurity">
<beans:property name="authentication_failure_url" value="/login.jsp?error=1"></beans:property>
</beans:bean>
<beans:bean class="com.my.filter.MDCFilter" name="mdcFilter"></beans:bean>
</beans:beans>