security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:security="http://www.springframework.org/schema/security"
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-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.2.xsd">
<!-- 此资源不需要保护 -->
<security:http pattern="/index.jsp*" security="none"></security:http>
<security:http pattern="/css/**" security="none"></security:http>
<security:http pattern="/jquery/**" security="none"></security:http>
<security:http auto-config="false" entry-point-ref="loginUrlEntryPoint">
<security:custom-filter ref="customFilter" before="FORM_LOGIN_FILTER"/>
<!-- 将自定义登陆过滤器添加到 过滤器链中 -->
<security:custom-filter ref="formLoginFilter" position="FORM_LOGIN_FILTER"/>
<!-- 将自定义退出过滤器添加到 过滤器链中 -->
<security:custom-filter ref="logoutFilter" position="LOGOUT_FILTER"/>
<!-- 将自定义的rememeberMe 添加到过滤器链中 -->
<security:custom-filter ref="rememberMeFilter" after="FORM_LOGIN_FILTER"/>
<!-- 将自定义session并发filter 添加到过滤器链 -->
<security:custom-filter ref="concurrencyFilter" position="CONCURRENT_SESSION_FILTER"/>
<!-- 将自定义的filterSecurityInterceptor 添加到过滤器链中 -->
<security:custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR" />
<!-- 将自定义的ExceptionTransactionFitler添加到过滤器链 -->
<security:custom-filter ref="exceptionTranslationFilter" after="EXCEPTION_TRANSLATION_FILTER"/>
</security:http>
<!-- 定义异常转换filter -->
<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<constructor-arg name="authenticationEntryPoint" ref="loginUrlEntryPoint"/>
<property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</bean>
<bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp"/>
</bean>
<!-- 定义授权管理filter -->
<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="customAccessDecisionManager"/>
<property name="securityMetadataSource" ref="customFilterInvocationSecurityMetadataSource"/>
</bean>
<!-- 处理session并发 -->
<bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
<constructor-arg name="sessionRegistry" ref="sessionRegistry"/>
<constructor-arg name="sessionInformationExpiredStrategy" ref="sessionInformationExpiredStrategy"/>
</bean>
<bean id="sessionInformationExpiredStrategy" class="org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy">
<constructor-arg name="invalidSessionUrl" value="/invalidSessionUrl.html"/>
<constructor-arg name="redirectStrategy" ref="redirectStrategy"/>
</bean>
<bean id="redirectStrategy" class="org.springframework.security.web.DefaultRedirectStrategy">
<property name="contextRelative" value="true"/>
</bean>
<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
<bean id="sas" class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/>
<!-- 处理rememberMe的请求 -->
<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
</bean>
<!-- 用来产生cookie -->
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<constructor-arg name="key" value="bunnyTouchspringRocks"/>
<constructor-arg name="userDetailsService" ref="customUserDetailsService"/>
<property name="cookieName" value="SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY"/>
<property name="tokenValiditySeconds" value="3600"/>
<property name="parameter" value="rememberMe"/>
<!-- <property name="cookieDomain" value=""/> -->
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<constructor-arg name="key" value="bunnyTouchspringRocks"/>
</bean>
<!-- 定义处理退出请求的fitler -->
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<property name="filterProcessesUrl" value="/user/tuichu.do"></property>
<constructor-arg index="0" value="/myLogin.jsp"></constructor-arg>
<constructor-arg index="1">
<list>
<!--销毁sesson -->
<ref bean="sessionInvalidateHandler"></ref>
<!--清除cookie -->
<ref bean="rememberMeServices"></ref>
</list>
</constructor-arg>
</bean>
<!-- 定义销毁session的处理类 -->
<bean id="sessionInvalidateHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"></bean>
<!--定义处理登陆请求的filter -->
<bean id="formLoginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="usernameParameter" value="uname"/>
<property name="passwordParameter" value="upassword"/>
<property name="filterProcessesUrl" value="/user/userLogin.do"/>
<property name="authenticationSuccessHandler" ref="authenSuccessHandler"/>
<property name="authenticationFailureHandler" ref="authenFailerHandler"/>
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="sessionAuthenticationStrategy" ref="sas"/>
</bean>
<!-- 定义认证成功后的处理类 -->
<bean id="authenSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="alwaysUseDefaultTargetUrl" value="false"></property>
<property name="defaultTargetUrl" value="/main.jsp"></property>
</bean>
<!-- 定义认证失败的处理类 -->
<bean id="authenFailerHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/loginError.jsp"> </property>
</bean>
<!-- 定义认证入口页面 -->
<bean id="loginUrlEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg name="loginFormUrl" value="/myLogin.jsp"></constructor-arg>
</bean>
<!-- 认证管理器
erase-credentials:默认认证成功后,会清除所有的认证凭据信息
如果有rememberMe,erase-credentials必须为false
-->
<security:authentication-manager alias="authenticationManager" erase-credentials="false">
<security:authentication-provider user-service-ref="customUserDetailsService">
<!-- 自定义加密算法 -->
<security:password-encoder ref="customPasswordEncoder"/>
</security:authentication-provider>
<security:authentication-provider ref="rememberMeAuthenticationProvider"/>
</security:authentication-manager>
</beans>
web.xml
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<!-- SpringSecurity必须的filter -->
<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>
CustomAccessDecisionManager.java
这里没有做任何业务处理,具体业务处理自己写
package net.bunnytouch.bs.security;
import java.util.Collection;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
@Component
public class CustomAccessDecisionManager implements AccessDecisionManager {
/**
* authentication: 访问受限资源的用户
* object:当前正在访问的受限资源
* configAttributes: 访问当前受限资源所需要的角色信息
*/
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
}
public boolean supports(ConfigAttribute attribute) {
return true;
}
public boolean supports(Class<?> clazz) {
return true;
}
}
customFilterInvocationSecurityMetadataSource.java
package net.bunnytouch.bs.security;
import java.util.Collection;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
@Component
public class customFilterInvocationSecurityMetadataSource implements
FilterInvocationSecurityMetadataSource {
//obj: 当前正在访问的受限资源 /user/queryAll.do
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
return null;
}
//当服务器启动的时候,从此方法将所有权限相关的配置属性加载到内存中
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
public boolean supports(Class<?> clazz) {
return true;
}
}
CustomPasswordEncoder.java
这个方法是自定义密码的加密方式。
官方推荐直接用BCryptPasswordEncoder
所以这里可以不需要做任何业务处理,也可以放弃这个类直接创建BCryptPasswordEncoder的bean对象(在security.xml配置里面对应的引用改过来就可以了)
package net.bunnytouch.bs.security;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class CustomPasswordEncoder extends BCryptPasswordEncoder implements PasswordEncoder {
}
CustomUserDetailsService.java
package net.bunnytouch.bs.security;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class CustomUserDetailsService implements UserDetailsService {
/**
*
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
return null;
}
}
CustomFilter.java
自定义的过滤器。
package net.bunnytouch.bs.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.stereotype.Component;
/**
* Servlet Filter implementation class CustomFilter
*/
@Component
public class CustomFilter implements Filter {
/**
* Default constructor.
*/
public CustomFilter() {
}
/**
* @see Filter#destroy()
*/
public void destroy() {
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
}
}