<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:egov-security="http://www.egovframe.go.kr/schema/egov-security"
	xmlns:security="http://www.springframework.org/schema/security"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
		http://www.egovframe.go.kr/schema/egov-security http://www.egovframe.go.kr/schema/egov-security/egov-security-3.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<bean id="concurrencyFilter"
		class="org.springframework.security.web.session.ConcurrentSessionFilter">
		<constructor-arg ref="sessionRegistry" />
		<constructor-arg value="/loginView.do" />
	</bean>

	<bean id="sas"
		class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
		<constructor-arg>
			<list>
				<bean
					class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
					<constructor-arg ref="sessionRegistry" />
					<property name="maximumSessions" value="1" />
					<property name="exceptionIfMaximumExceeded" value="true" />
				</bean>
				<bean
					class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
				</bean>
				<bean
					class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
					<constructor-arg ref="sessionRegistry" />
				</bean>
			</list>
		</constructor-arg>
	</bean>
	
	<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
	<security:http auto-config="true" use-expressions="true">
		<security:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
		
		<security:session-management session-authentication-strategy-ref="sas" invalid-session-url="/loginView.do"/>
		<!-- <security:session-management invalid-session-url="/loginView.do">
 			<security:concurrency-control 
 				session-registry-ref="sessionRegistry"
 				expired-url="/loginView.do?error=2"/>
		</security:session-management> -->
	
		<!-- Filter 제외 URL -->
		<security:intercept-url pattern="/css/**" access="permitAll" />
		<security:intercept-url pattern="/images/**" access="permitAll" />
		<security:intercept-url pattern="/storage/**" access="permitAll" />
		<security:intercept-url pattern="/js/**" access="permitAll" />
		<security:intercept-url pattern="/loginView.do*" access="permitAll" />
		
		<!-- Login 처리 -->
		<security:form-login login-processing-url="/j_spring_security_check"
			login-page="/loginView.do"
			always-use-default-target="true" 
			default-target-url="/main.do"
			authentication-failure-url="/loginView.do?error=1" 
			authentication-success-handler-ref="loginSuccessHandler"
		/>

		<!-- Logout처리 -->
		<security:logout 
			logout-url="/j_spring_security_logout" 
			invalidate-session="true" 
			success-handler-ref="logoutsuccessHandler" />

		<!-- 접근 권한 에러 URL -->			
		<security:access-denied-handler error-page="/accessDenied.do"/>
			
		<!-- 로그인하지 않은 사용자에게 익명 사용자 롤 부여 -->
		<security:anonymous granted-authority="ANONYMOUS_USER"/>
			
		<!-- Custom filter 적용 -->
		<security:custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="filterSecurityInterceptor"/>

	</security:http>
	
	<!-- Login Success Handler -->
	<bean id="loginSuccessHandler" class="kcg.faics.sec.LoginSuccessHandler">
		<property name="successUrl" value="/main.do"></property>
	</bean>
	<!-- /Login Success Handler -->
	
	<!-- Logout Success Handler -->
	<bean id="logoutsuccessHandler" class="kcg.faics.sec.LogoutSuccessHandler">
		<property name="successUrl" value="/loginView.do"></property>
	</bean>
	<!-- /Logout Success Handler -->
	

	<!-- Security Provider 설정 -->
	<!-- 
		참조
		http://syaku.tistory.com/286
		http://zest133.tistory.com/entry/Spring-Security-login2
		http://spring-security.blogspot.kr/
	 -->
	<security:authentication-manager>
		<security:authentication-provider ref="CustomAuthenticationProvider" />
	</security:authentication-manager>

	<!-- AuthenticationProvider -->
	<bean id="CustomAuthenticationProvider" class="kcg.faics.sec.AuthenticationProvider">
		<property name="userDetailsService" ref="userService"></property>
		<property name="passwordEncoder" ref="passwordEncoder"></property>
	</bean>
	
	<bean id="userService" class="kcg.faics.sec.service.impl.SecurityServiceImpl">
		<property name="roleHierarchy" ref="roleHierarchy" />
	</bean>
	
	<bean id="passwordEncoder" class="kcg.faics.sec.ShaPasswordEncoderEx">
		<constructor-arg name="strength" value="256" />
	</bean>
	
	<!-- MD5 -->
	<!-- <bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"></bean> -->
	<!-- /MD5 -->
	
	<!-- Aria Encryption, Decryption -->
	<bean id="ariaEncoder" class="kcg.faics.sec.service.impl.AriaPasswordEncoder">
		<property name="ariaCryptoService" ref="ariaCryptoService" />
		<property name="hashKey" value="${Global.crypto.key}"/>
	</bean>
	
	<bean id="ariaCryptoService" class="egovframework.rte.fdl.cryptography.impl.EgovARIACryptoServiceImpl">
		<property name="passwordEncoder" ref="egovPasswordEncoder" />
		<property name="blockSize" value="1024"/>
	</bean>
	
	<bean id="egovPasswordEncoder" class="egovframework.rte.fdl.cryptography.EgovPasswordEncoder">
		<property name="algorithm" value="${Global.crypto.password.algorithm}"/>
		<property name="hashedPassword" value="${Global.crypto.hased.password}"/>
	</bean>
	<!-- /Aria Encryption, Decryption -->
	
	
	
	<!-- Role Hierarchy-->
	<!-- 참조 
		http://open.egovframe.go.kr/nforges/information/filearchive/8457/.do
	-->
	<bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
		<property name="hierarchy" ref="hierarchyStrings" />
		<!-- DB에서 권한 계층정보를 가져오는 과정이 여의치 않으면 직접 입력한다.
		<property name="hierarchy">
			<value>
				ROLE_ADMIN > ROLE_MANAGER
				ROLE_MANAGER > ROLE_FA
				ROLE_MANAGER > ROLE_NFA
				ROLE_FA > ROLE_USER
				ROLE_NFA > ROLE_USER
				ROLE_USER > ROLE_RESTRICTED
				ROLE_RESTRICTED > IS_AUTHENTICATED_FULLY
				IS_AUTHENTICATED_FULLY >	IS_AUTHENTICATED_REMEMBERED
				IS_AUTHENTICATED_REMEMBERED > IS_AUTHENTICATED_ANONYMOUSLY
			</value>
		</property>
		-->
	</bean>	
	<bean id="hierarchyStrings" class="kcg.faics.sec.role.HierarchyStringsFactoryBean" init-method="init" />	
	<!-- /Role Hierarchy-->
	
	
	<!-- Role & Url Management -->
	<!-- 참조 
		http://open.egovframe.go.kr/nforges/information/filearchive/8457/.do
		http://zgundam.tistory.com/58
		http://zgundam.tistory.com/59
	 -->
	<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
		<property name="authenticationManager" ref="org.springframework.security.authenticationManager" />
		<property name="accessDecisionManager" ref="accessDecisionManager" />
		<property name="securityMetadataSource" ref="reloadableFilterInvocationSecurityMetadataSource" />
	</bean>
	
	<bean id="reloadableFilterInvocationSecurityMetadataSource" class="kcg.faics.sec.filter.ReloadableFilterInvocationSecurityMetadataSource">
		<constructor-arg ref="requestMap"/>
	</bean>
	
	<bean id="requestMap" class="kcg.faics.sec.filter.SecurityUrlResourcesMapFactoryBean" init-method="init" /> 
	
	<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
		<property name="allowIfAllAbstainDecisions" value="false" />
		<constructor-arg name="decisionVoters">
			<list>
				<bean class="org.springframework.security.access.vote.RoleVoter">
					<property name="rolePrefix" value="" />
				</bean>
			</list>
		</constructor-arg>
	</bean>
	<!-- /Role & Url Management - -->
	
</beans>