package com.hwlcn.security.spring.web; import com.hwlcn.security.config.Ini; import com.hwlcn.security.util.CollectionUtils; import com.hwlcn.security.util.Nameable; import com.hwlcn.security.util.StringUtils; import com.hwlcn.security.web.filter.AccessControlFilter; import com.hwlcn.security.web.filter.authc.AuthenticationFilter; import com.hwlcn.security.web.filter.authc.LogoutFilter; import com.hwlcn.security.web.filter.authz.AuthorizationFilter; import com.hwlcn.security.web.filter.mgt.DefaultFilterChainManager; import com.hwlcn.security.web.filter.mgt.FilterChainManager; import com.hwlcn.security.web.filter.mgt.FilterChainResolver; import com.hwlcn.security.web.filter.mgt.PathMatchingFilterChainResolver; import com.hwlcn.security.web.mgt.WebSecurityManager; import com.hwlcn.security.web.servlet.AbstractSecurityFilter; import com.hwlcn.security.mgt.SecurityManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.BeanPostProcessor; import javax.servlet.Filter; import java.util.LinkedHashMap; import java.util.Map; public class SecurityFilterFactoryBean implements FactoryBean, BeanPostProcessor { private static transient final Logger log = LoggerFactory.getLogger(SecurityFilterFactoryBean.class); public static final String URLS = "urls"; private SecurityManager securityManager; private Map<String, Filter> filters; private Map<String, String> filterChainDefinitionMap; private String loginUrl; private String successUrl; private String unauthorizedUrl; private String logoutRedirectUrl; private AbstractSecurityFilter instance; public SecurityFilterFactoryBean() { this.filters = new LinkedHashMap<String, Filter>(); this.filterChainDefinitionMap = new LinkedHashMap<String, String>(); } public SecurityManager getSecurityManager() { return securityManager; } public void setSecurityManager(SecurityManager securityManager) { this.securityManager = securityManager; } public String getLoginUrl() { return loginUrl; } public void setLoginUrl(String loginUrl) { this.loginUrl = loginUrl; } public String getSuccessUrl() { return successUrl; } public void setSuccessUrl(String successUrl) { this.successUrl = successUrl; } public String getUnauthorizedUrl() { return unauthorizedUrl; } public void setUnauthorizedUrl(String unauthorizedUrl) { this.unauthorizedUrl = unauthorizedUrl; } public Map<String, Filter> getFilters() { return filters; } public void setFilters(Map<String, Filter> filters) { this.filters = filters; } public Map<String, String> getFilterChainDefinitionMap() { return filterChainDefinitionMap; } public void setFilterChainDefinitionMap(Map<String, String> filterChainDefinitionMap) { this.filterChainDefinitionMap = filterChainDefinitionMap; } public void setFilterChainDefinitions(String definitions) { Ini ini = new Ini(); ini.load(definitions); Ini.Section section = ini.getSection(URLS); if (CollectionUtils.isEmpty(section)) { section = ini.getSection(Ini.DEFAULT_SECTION_NAME); } setFilterChainDefinitionMap(section); } public Object getObject() throws Exception { if (instance == null) { instance = createInstance(); } return instance; } public Class getObjectType() { return SpringSecurityFilter.class; } public boolean isSingleton() { return true; } protected FilterChainManager createFilterChainManager() { DefaultFilterChainManager manager = new DefaultFilterChainManager(); Map<String, Filter> defaultFilters = manager.getFilters(); for (Filter filter : defaultFilters.values()) { applyGlobalPropertiesIfNecessary(filter); } Map<String, Filter> filters = getFilters(); if (!CollectionUtils.isEmpty(filters)) { for (Map.Entry<String, Filter> entry : filters.entrySet()) { String name = entry.getKey(); Filter filter = entry.getValue(); applyGlobalPropertiesIfNecessary(filter); if (filter instanceof Nameable) { ((Nameable) filter).setName(name); } manager.addFilter(name, filter, false); } } Map<String, String> chains = getFilterChainDefinitionMap(); if (!CollectionUtils.isEmpty(chains)) { for (Map.Entry<String, String> entry : chains.entrySet()) { String url = entry.getKey(); String chainDefinition = entry.getValue(); manager.createChain(url, chainDefinition); } } return manager; } protected AbstractSecurityFilter createInstance() throws Exception { if (log.isDebugEnabled()) { log.debug("Creating Secirity Filter instance."); } SecurityManager securityManager = getSecurityManager(); if (securityManager == null) { String msg = "SecurityManager property must be set."; throw new BeanInitializationException(msg); } if (!(securityManager instanceof WebSecurityManager)) { String msg = "The security manager does not implement the WebSecurityManager interface."; throw new BeanInitializationException(msg); } FilterChainManager manager = createFilterChainManager(); PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver(); chainResolver.setFilterChainManager(manager); return new SpringSecurityFilter((WebSecurityManager) securityManager, chainResolver); } private void applyLoginUrlIfNecessary(Filter filter) { String loginUrl = getLoginUrl(); if (StringUtils.hasText(loginUrl) && (filter instanceof AccessControlFilter)) { AccessControlFilter acFilter = (AccessControlFilter) filter; String existingLoginUrl = acFilter.getLoginUrl(); if (AccessControlFilter.DEFAULT_LOGIN_URL.equals(existingLoginUrl)) { acFilter.setLoginUrl(loginUrl); } } } private void applyLogoutRedirectUrlIfNecessary(Filter filter) { String logoutRedirectUrl = getLogoutRedirectUrl(); if (StringUtils.hasText(logoutRedirectUrl) && (filter instanceof LogoutFilter)) { LogoutFilter logoutFilter = (LogoutFilter) filter; String existingLoginUrl = logoutFilter.getRedirectUrl(); if (LogoutFilter.DEFAULT_REDIRECT_URL.equals(existingLoginUrl)) { logoutFilter.setRedirectUrl(logoutRedirectUrl); } } } private void applySuccessUrlIfNecessary(Filter filter) { String successUrl = getSuccessUrl(); if (StringUtils.hasText(successUrl) && (filter instanceof AuthenticationFilter)) { AuthenticationFilter authcFilter = (AuthenticationFilter) filter; String existingSuccessUrl = authcFilter.getSuccessUrl(); if (AuthenticationFilter.DEFAULT_SUCCESS_URL.equals(existingSuccessUrl)) { authcFilter.setSuccessUrl(successUrl); } } } private void applyUnauthorizedUrlIfNecessary(Filter filter) { String unauthorizedUrl = getUnauthorizedUrl(); if (StringUtils.hasText(unauthorizedUrl) && (filter instanceof AuthorizationFilter)) { AuthorizationFilter authzFilter = (AuthorizationFilter) filter; String existingUnauthorizedUrl = authzFilter.getUnauthorizedUrl(); if (existingUnauthorizedUrl == null) { authzFilter.setUnauthorizedUrl(unauthorizedUrl); } } } private void applyGlobalPropertiesIfNecessary(Filter filter) { applyLoginUrlIfNecessary(filter); applySuccessUrlIfNecessary(filter); applyUnauthorizedUrlIfNecessary(filter); applyLogoutRedirectUrlIfNecessary(filter);//退出后跳转界面 } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Filter) { if (log.isDebugEnabled()) { log.debug("Found filter chain candidate filter '{}'", beanName); } Filter filter = (Filter) bean; applyGlobalPropertiesIfNecessary(filter); getFilters().put(beanName, filter); } else { if (log.isTraceEnabled()) { log.trace("Ignoring non-Filter bean '{}'", beanName); } } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } private static final class SpringSecurityFilter extends AbstractSecurityFilter { protected SpringSecurityFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) { super(); if (webSecurityManager == null) { throw new IllegalArgumentException("WebSecurityManager property cannot be null."); } setSecurityManager(webSecurityManager); if (resolver != null) { setFilterChainResolver(resolver); } } } public String getLogoutRedirectUrl() { return logoutRedirectUrl; } public void setLogoutRedirectUrl(String logoutRedirectUrl) { this.logoutRedirectUrl = logoutRedirectUrl; } }