package cn.com.taiji;

import java.io.File;
import java.io.FileInputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

import javax.inject.Inject;
import javax.servlet.MultipartConfigElement;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.Banner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.web.MultipartProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
//import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import org.thymeleaf.dialect.IDialect;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.fasterxml.jackson.datatype.joda.JodaModule;

import cn.com.taiji.safety.RefererFilter;
import cn.com.taiji.safety.permission.PermissionFilter;
import cn.com.taiji.safety.xss.XssFilter;
import cn.com.taiji.security.MyAuthenticationProvider;
import cn.com.taiji.security.MyFailureHandler;
import cn.com.taiji.security.MyFilterSecurityInterceptor;
import cn.com.taiji.security.MySecurityMetadataSource;
import cn.com.taiji.security.MySuccessHandler;
import cn.com.taiji.security.MyUserDetailServiceImpl;
import cn.com.taiji.security.MyUsernamePasswordAuthenticationFilter;
import cn.com.taiji.sys.json.SysModule;
import cn.com.taiji.sys.service.LoadingCacheService;
import cn.com.taiji.sys.service.MenuService;
import cn.com.taiji.sys.service.RoleService;
import cn.com.taiji.sys.service.UserService;

@EnableTransactionManagement // 开始事务管理配置
@SpringBootApplication
//@EnableRedisHttpSession
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@AutoConfigureAfter(JacksonAutoConfiguration.class)
@EnableAutoConfiguration(exclude = { org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class,
		org.activiti.spring.boot.SecurityAutoConfiguration.class,
		org.springframework.boot.actuate.autoconfigure.ManagementWebSecurityAutoConfiguration.class })

/**
 * 
 * @ClassName: Application
 * @Description: 工程配置类
 * @author lijiezhi_pc
 * @date 2017年11月22日 下午3:45:29
 *
 */
public class Application extends WebMvcConfigurerAdapter implements CommandLineRunner {
	/*
	 * Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
	 * No qualifying bean of type [org.springframework.core.task.TaskExecutor] is
	 * defined: expected single matching bean but found 4:
	 * clientInboundChannelExecutor, clientOutboundChannelExecutor,
	 * brokerChannelExecutor, messageBrokerTaskScheduler 解决springboot 集成websocket报错
	 */
	@Bean
	public TaskExecutor taskExecutor() {
		return new SimpleAsyncTaskExecutor();
	}

	static {
		System.setProperty("jasypt.encryptor.password", "123456");
	}


	@Override
	public void run(String... strings) throws Exception {
//		String basePath = "/Users/hujie/Documents/dev/git-repo/taiji/tianjin-cgw/zyml/cn.com.taiji.system/src/main/resources/static/diagrams";
////		1、创建ProcessEngine
//		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
////        2、得到RepositoryService实例
//		RepositoryService repositoryService = processEngine.getRepositoryService();
////        3、使用RepositoryService进行部署
//		Deployment deployment = repositoryService.createDeployment()
//				.addInputStream("dataPreparation.bpmn", new FileInputStream(new File(basePath + "/dataPreparation.bpmn")))
//				.addInputStream("dataPreparation.png", new FileInputStream(new File(basePath + "/dataPreparation.png")))
//				.name("dataPreparation")
//				.deploy();
//		deployment = repositoryService.createDeployment()
//				.addInputStream("fwSq.bpmn", new FileInputStream(new File(basePath + "/fwSq.bpmn")))
//				.addInputStream("fwSq.png", new FileInputStream(new File(basePath + "/fwSq.png")))
//				.name("服务申请")
//				.deploy();
//		deployment = repositoryService.createDeployment()
//				.addInputStream("fwZc.bpmn", new FileInputStream(new File(basePath + "/fwZc.bpmn")))
//				.addInputStream("fwZc.png", new FileInputStream(new File(basePath + "/fwZc.png")))
//				.name("服务注册")
//				.deploy();
//		deployment = repositoryService.createDeployment()
//				.addInputStream("infoClassZc.bpmn", new FileInputStream(new File(basePath + "/infoClassZc.bpmn")))
//				.addInputStream("infoClassZc.png", new FileInputStream(new File(basePath + "/infoClassZc.png")))
//				.name("信息类注册")
//				.deploy();
//		deployment = repositoryService.createDeployment()
//				.addInputStream("requireInfo.bpmn", new FileInputStream(new File(basePath + "/requireInfo.bpmn")))
//				.addInputStream("requireInfo.png", new FileInputStream(new File(basePath + "/requireInfo.png")))
//				.name("requireInfo")
//				.deploy();
//		deployment = repositoryService.createDeployment()
//				.addInputStream("shareApply.bpmn", new FileInputStream(new File(basePath + "/shareApply.bpmn")))
//				.addInputStream("shareApply.png", new FileInputStream(new File(basePath + "/shareApply.png")))
//				.name("信息类共享")
//				.deploy();
	}

	@Bean
	public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(20);
		executor.setMaxPoolSize(100);
		executor.setQueueCapacity(8);
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 对拒绝task的处理策略
		executor.setKeepAliveSeconds(60);
		executor.initialize();
		return executor;
	}

	@Bean
	public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
		MappingJackson2HttpMessageConverter reg = new MappingJackson2HttpMessageConverter();
		List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
		supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
		supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
		supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
		supportedMediaTypes.add(MediaType.TEXT_PLAIN);
		reg.setSupportedMediaTypes(supportedMediaTypes);
		return reg;
	}

	@Bean
	public ServletRegistrationBean druidServlet() {
		ServletRegistrationBean reg = new ServletRegistrationBean();
		reg.setServlet(new StatViewServlet());
		reg.addUrlMappings("/druid/*");
		reg.addInitParameter("loginUsername", "admin");
		reg.addInitParameter("loginPassword", "Huawei@123");
		return reg;
	}

	@Bean
	@Primary
	public DataSource druidDataSource(@Value("${spring.datasource.driverClassName}") String driver,
			@Value("${spring.datasource.url}") String url, @Value("${spring.datasource.username}") String username,
			@Value("${spring.datasource.password}") String password) {
		DruidDataSource druidDataSource = new DruidDataSource();
		druidDataSource.setDriverClassName(driver);
		druidDataSource.setUrl(url);
		druidDataSource.setDbType("postgresql");
		druidDataSource.setUsername(username);
		druidDataSource.setPassword(password);
		druidDataSource.setInitialSize(10);
		druidDataSource.setMinIdle(5);
		druidDataSource.setMaxActive(800);
		druidDataSource.setMaxWait(60000);// 4秒
		druidDataSource.setKeepAlive(true);
		druidDataSource.setTimeBetweenEvictionRunsMillis(60000);
		druidDataSource.setMinEvictableIdleTimeMillis(300000);
		druidDataSource.setValidationQuery("select 1 ");
		druidDataSource.setTestWhileIdle(true);
		druidDataSource.setTestOnBorrow(true);
		druidDataSource.setRemoveAbandoned(true);
		druidDataSource.setRemoveAbandonedTimeout(1800);
		druidDataSource.setLogAbandoned(true);
		druidDataSource.setTestOnReturn(true);
		druidDataSource.setPoolPreparedStatements(true);
		druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
		try {
			druidDataSource.setFilters("stat, wall");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return druidDataSource;
	}

//	@Bean(name = "secondaryDataSource")
//    @Qualifier("secondaryDataSource")
//    public DataSource secondaryDataSource(@Value("${spring.datasource2.driverClassName}") String driver,
//                                      @Value("${spring.datasource2.url}") String url,
//                                      @Value("${spring.datasource2.username}") String username,
//                                      @Value("${spring.datasource2.password}") String password) {
//        DruidDataSource druidDataSource = new DruidDataSource();
//        druidDataSource.setDriverClassName(driver);
//        druidDataSource.setUrl(url);
//        druidDataSource.setUsername(username);
//        druidDataSource.setPassword(password);
//        druidDataSource.setInitialSize(100);
//        druidDataSource.setMinIdle(10);
//        druidDataSource.setMaxActive(400);
//        druidDataSource.setMaxWait(6000);
//        druidDataSource.setTimeBetweenEvictionRunsMillis(60000);
//        druidDataSource.setMinEvictableIdleTimeMillis(300000);
//        druidDataSource.setValidationQuery(" select 1 from dual");
//        druidDataSource.setTestWhileIdle(true);
//        druidDataSource.setTestOnBorrow(true);
//        druidDataSource.setRemoveAbandoned(true);
//        druidDataSource.setRemoveAbandonedTimeout(18000);
//        druidDataSource.setLogAbandoned(true);
//        druidDataSource.setTestOnReturn(false);
//        druidDataSource.setPoolPreparedStatements(true);
//        druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
//        try {
//            druidDataSource.setFilters("stat, wall");
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }
//        return druidDataSource;
//    }
	@Bean
	public SessionRegistry sessionRegistry() {
		SessionRegistry sessionRegistry = new SessionRegistryImpl();
		return sessionRegistry;
	}

	@Bean
	public MySessionControlStrategy concurrentSessionControlStrategy() {
		MySessionControlStrategy concurrentSessionControlStrategy = new MySessionControlStrategy(sessionRegistry());
		return concurrentSessionControlStrategy;
	}

	@Bean
	public FilterRegistrationBean filterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(new WebStatFilter());
		filterRegistrationBean.addUrlPatterns("/*");
		filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
		return filterRegistrationBean;
	}

	@Bean
	public FilterRegistrationBean encodeRegistrationBean() {
		CharacterEncodingFilter encodeFilter = new CharacterEncodingFilter();
		encodeFilter.setEncoding("UTF-8");
		encodeFilter.setForceEncoding(true);
		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
		registrationBean.setFilter(encodeFilter);
		registrationBean.setOrder(Ordered.LOWEST_PRECEDENCE);
		return registrationBean;
	}

	public static void main(String[] args) {
		SpringApplication app = new SpringApplication(Application.class);
		app.setBannerMode(Banner.Mode.OFF);
		app.run(args);
	}

	@Bean
	public ObjectMapper jacksonObjectMapper() {
		return new ObjectMapper().registerModule(new JodaModule()).disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
				.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
				.configure(SerializationFeature.INDENT_OUTPUT, true).setDateFormat(new ISO8601DateFormat())
				.registerModule(new SysModule());

	}

	@Bean
	public MappingJackson2JsonView mappingJackson2JsonView() {
		MappingJackson2JsonView v = new org.springframework.web.servlet.view.json.MappingJackson2JsonView();
		v.setObjectMapper(jacksonObjectMapper());
		v.setPrettyPrint(true);
		return v;
	}

	protected class MappingJackson2JsonpView extends MappingJackson2JsonView {
		public static final String DEFAULT_CONTENT_TYPE = "application/javascript";

		@Override
		public String getContentType() {
			return DEFAULT_CONTENT_TYPE;
		}

		@Override
		public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
				throws Exception {
			Map<String, String[]> params = request.getParameterMap();
			if (params.containsKey("callback")) {
				response.getOutputStream().write(new String(params.get("callback")[0] + "(").getBytes());
				super.render(model, request, response);
				response.getOutputStream().write(new String(");").getBytes());
				response.setContentType(DEFAULT_CONTENT_TYPE);
			} else {
				super.render(model, request, response);
			}
		}
	}

	@Bean
	public MappingJackson2JsonpView mappingJackson2JsonpView() {
		MappingJackson2JsonpView v = new MappingJackson2JsonpView();
		v.setObjectMapper(jacksonObjectMapper());
		v.setPrettyPrint(false);
		return v;
	}

	@Autowired
	ThymeleafViewResolver thymeleafViewResolver;

	@Override
	public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
		configurer.favorParameter(true).ignoreAcceptHeader(false).defaultContentType(MediaType.TEXT_HTML)
				.mediaType("json", MediaType.APPLICATION_JSON)
				.mediaType("jsonp", MediaType.valueOf("application/javascript"));
	}

	@Bean
	public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
		List<ViewResolver> resolvers = new ArrayList<ViewResolver>();

		thymeleafViewResolver.setCache(false);
		// thymeleafViewResolver.setOrder(1);
		resolvers.add(thymeleafViewResolver);

		// InternalResourceViewResolver r2 = new InternalResourceViewResolver();
		// r2.setPrefix("templates");
		// r2.setSuffix(".jsp");
		// resolvers.add(r2);

		ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
		resolver.setViewResolvers(resolvers);
		resolver.setContentNegotiationManager(manager);

		List<View> views = new ArrayList<View>();
		views.add(mappingJackson2JsonView());
		views.add(mappingJackson2JsonpView());
		resolver.setDefaultViews(views);
		return resolver;
	}

	// see
	// org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration.ThymeleafDefaultConfiguration

	@Bean
	public Collection<IDialect> dialects() {
		Collection<IDialect> dialects = new HashSet<IDialect>();
		dialects.add(new SpringSecurityDialect());

		return dialects;
	}

	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/zcgllogin").setViewName("login");

	}

	@Order(Ordered.HIGHEST_PRECEDENCE)
	@Configuration
	protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {

		// @Value("${spring.datasource.url}")
		// private String url;

		// @Autowired
		// private JdbcTemplate jt;
		//
		@Autowired
		private DataSource dataSource;
		@Autowired
		private SessionRegistry sessionRegistry;

		@Bean
		public ShaPasswordEncoder passwordEncoder() {
			// return new BCryptPasswordEncoder();
			return new ShaPasswordEncoder(1);
		}

		// @Autowired
		// public TaijiAuthenticationProvider customAuthenticationProvider;
		@Inject
		public MyUserDetailServiceImpl userDetailsService;

		@Override
		public void init(AuthenticationManagerBuilder auth) throws Exception {
			auth.userDetailsService(userDetailsService);
			// auth.authenticationProvider(customAuthenticationProvider);
			// @formatter:off
			// auth.jdbcAuthentication()
			// .dataSource(dataSource)
			// .passwordEncoder(passwordEncoder())
			// .groupAuthoritiesByUsername(
			// "select g.code, g.name, ga.role_code from user_group g, user_account_group
			// gm, user_group_role ga where gm.user_code = ? and g.code = ga.group_code and
			// g.code = gm.group_code and g.enabled = true")
			// .authoritiesByUsernameQuery(
			// "select x.user_code, x.role_code from user_account_role x, user_role r where
			// x.role_code=r.code and r.enabled = true and x.user_code=?")
			// .usersByUsernameQuery(
			// "select code, password, enabled from user_account where code=? and enabled =
			// true");
			// @formatter:off
			// auth.inMemoryAuthentication().withUser("admin").password("admin")
			// .roles("ADMIN", "USER").and().withUser("user")
			// .password("user").roles("USER");
			// @formatter:on
		}
	}

	@Autowired
	private MultipartProperties multipartProperties = new MultipartProperties();

	@Bean
	@ConditionalOnMissingBean
	public MultipartConfigElement multipartConfigElement() {
		this.multipartProperties.setMaxFileSize("-1");
		this.multipartProperties.setMaxRequestSize("-1");
		return this.multipartProperties.createMultipartConfig();
	}

	@Bean
	@ConditionalOnMissingBean
	public StandardServletMultipartResolver multipartResolver() {
		return new StandardServletMultipartResolver();
	}

	@Order(Ordered.LOWEST_PRECEDENCE - 8)
	protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {

		@Autowired
		private LoadingCacheService loadingCacheService;

		@Autowired
		private UserService userService;
		@Autowired
		private MySessionControlStrategy concurrentSessionControlStrategy;
		@Value("${pwd.invaliddays}")
		public int invaliddays;
		@Value("${pwd.invalid}")
		public boolean invalid;
		@Value("${concurrency.control}")
		public boolean concurrencyControl;
		@Value("${concurrency.limit}")
		public int concurrencyLimit;
		@Value("${concurrency.priority}")
		public int concurrencyPriority;
		@Value("${concurrency.hour_start}")
		public int concurrencyHourStart;
		@Value("${concurrency.hour_end}")
		public int concurrencyHourEnd;
		@Inject
		SessionRegistryImpl sessionRegistryImpl;

		@Bean
		public MyUsernamePasswordAuthenticationFilter loginFilter() throws Exception {
			MyUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter = new MyUsernamePasswordAuthenticationFilter();
			customUsernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(customSuccessHandler());
			customUsernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(customFailureHandler());
			customUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
			customUsernamePasswordAuthenticationFilter.setLoadingCacheService(loadingCacheService);
			customUsernamePasswordAuthenticationFilter.setInvalid(invalid);
			customUsernamePasswordAuthenticationFilter.setSessionRegistryImpl(sessionRegistryImpl);
			customUsernamePasswordAuthenticationFilter.setInvaliddays(invaliddays);
			customUsernamePasswordAuthenticationFilter.setConcurrencyControl(concurrencyControl);
			customUsernamePasswordAuthenticationFilter.setConcurrencyLimit(concurrencyLimit);
			customUsernamePasswordAuthenticationFilter.setConcurrencyPriority(concurrencyPriority);
			customUsernamePasswordAuthenticationFilter.setConcurrencyHourStart(concurrencyHourStart);
			customUsernamePasswordAuthenticationFilter.setConcurrencyHourEnd(concurrencyHourEnd);
			customUsernamePasswordAuthenticationFilter
					.setSessionAuthenticationStrategy(concurrentSessionControlStrategy);
			customUsernamePasswordAuthenticationFilter.setUserService(userService);
			customUsernamePasswordAuthenticationFilter.setFilterProcessesUrl("/login");
			customUsernamePasswordAuthenticationFilter.setAllowEmptyValidateCode(true);
			return customUsernamePasswordAuthenticationFilter;
		}

		@Bean
		public MyFailureHandler customFailureHandler() {
			MyFailureHandler customFailureHandler = new MyFailureHandler();
			customFailureHandler.setDefaultFailureUrl("/zcgllogin");
			return customFailureHandler;
		}

		@Bean
		public MySuccessHandler customSuccessHandler() {
			MySuccessHandler customSuccessHandler = new MySuccessHandler();
			customSuccessHandler.setDefaultTargetUrl("/dbdc/sysframe");
			return customSuccessHandler;
		}

		@Bean
		@Override
		public AuthenticationManager authenticationManagerBean() throws Exception {
			List<AuthenticationProvider> authenticationProviderList = new ArrayList<AuthenticationProvider>();
			authenticationProviderList.add(customAuthenticationProvider());
			AuthenticationManager authenticationManager = new ProviderManager(authenticationProviderList);
			return authenticationManager;
		}

		@Autowired
		public MyUserDetailServiceImpl userDetailsService;

		@Bean
		private MyAuthenticationProvider customAuthenticationProvider() {
			MyAuthenticationProvider customAuthenticationProvider = new MyAuthenticationProvider();
			customAuthenticationProvider.setUserDetailsService(userDetailsService);
			return customAuthenticationProvider;
		}

		@Autowired
		private MenuService menuService;
		@Autowired
		private RoleService roleService;
		@Autowired
		private SessionRegistry sessionRegistry;

		@Bean
		private MySecurityMetadataSource fisMetadataSource() {
			MySecurityMetadataSource fisMetadataSource = new MySecurityMetadataSource();
			fisMetadataSource.setMenuService(menuService);
			fisMetadataSource.setRoleService(roleService);
			return fisMetadataSource;
		}

		@Autowired
		private cn.com.taiji.security.MyAccessDecisionManager accessDecisionManager;

		@Bean
		public MyFilterSecurityInterceptor taijifiltersecurityinterceptor() throws Exception {
			MyFilterSecurityInterceptor taijifiltersecurityinterceptor = new MyFilterSecurityInterceptor();
			taijifiltersecurityinterceptor.setFisMetadataSource(fisMetadataSource());
			taijifiltersecurityinterceptor.setAccessDecisionManager(accessDecisionManager);
			taijifiltersecurityinterceptor.setAuthenticationManager(authenticationManagerBean());
			return taijifiltersecurityinterceptor;
		}

		@Override
		protected void configure(HttpSecurity http) throws Exception {
			// @formatter:off
			  http
			 .sessionManagement()
	            .sessionAuthenticationStrategy(concurrentSessionControlStrategy)
	            .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
	            .sessionFixation().changeSessionId()
	            .maximumSessions(1)
	            .maxSessionsPreventsLogin(true)
	            .expiredUrl("/dbdc/sysquit")
	            .sessionRegistry(sessionRegistry);
			http.authorizeRequests()

					.filterSecurityInterceptorOncePerRequest(true)// 过滤器的安全拦截器的每一次的要求
					.antMatchers("/image").permitAll() // for login
					.antMatchers("/dbdc/caslogin").permitAll().antMatchers("/dbdc/tjcaslogin").permitAll()
					.antMatchers("/dbdc/tjcaslogin").permitAll()
					.antMatchers("/dbdc/synchronizeInfo").permitAll().antMatchers("/monitor/isalive").permitAll()
					.antMatchers("/zcgllogin").permitAll().antMatchers("/dbdc_theme/**").permitAll()
					.antMatchers("/layuiadmin/**").permitAll().antMatchers("/layer/**").permitAll()
					.antMatchers("/api/**").permitAll().antMatchers("/echarts/**").permitAll()
					.antMatchers("/ueditor/**").permitAll().antMatchers("/uploadfile/**").permitAll()
					.antMatchers("/websocket-logger-js/**").permitAll().antMatchers("/soap/*").permitAll().anyRequest()
					.fullyAuthenticated()// .accessDecisionManager(accessDecisionManager) // all others need login
					.and().formLogin().loginPage("/zcgllogin").failureUrl("/zcgllogin?error")
					// login config
					.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
					.and().exceptionHandling().accessDeniedPage("/logout"); // exception
			http.csrf().disable().addFilterAfter(new PermissionFilter(), ChannelProcessingFilter.class)
			.addFilterAfter(new XssFilter(), ChannelProcessingFilter.class)
			// 增加PermissionFilter
					.addFilterAfter(new RefererFilter(), ChannelProcessingFilter.class).addFilter(loginFilter())
					.rememberMe();
			http.headers().frameOptions().disable();
			// @formatter:on
		}

		@Override
		public void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
			authManagerBuilder.userDetailsService(userDetailsService);
		}

	}

}