###############################################################
## ÀÛ¾÷ #1 ÇÁ·ÎÁ§Æ® ÁØºñ

## WEB-INF/lib
commons-logging.jar
org.springframework.aop-3.0.1.RELEASE.jar
org.springframework.asm-3.0.1.RELEASE.jar
org.springframework.beans-3.0.1.RELEASE.jar
org.springframework.context-3.0.1.RELEASE.jar
org.springframework.core-3.0.1.RELEASE.jar
org.springframework.expression-3.0.1.RELEASE.jar
org.springframework.transaction-3.0.1.RELEASE.jar
org.springframework.web-3.0.1.RELEASE.jar
spring-security-config-3.0.2.RELEASE.jar
spring-security-core-3.0.2.RELEASE.jar
spring-security-web-3.0.2.RELEASE.jar


###############################################################
## ÀÛ¾÷ #2 ÃÊ°£´Ü HTTP º¸¾È

## web.xml
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>WEB-INF/applicationContext*.xml</param-value>
	</context-param>

	<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>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>


## applicationContext-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans" 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-3.0.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.0.xsd">

	<http auto-config='true'>
		<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
	</http>

	<authentication-manager>
		<authentication-provider>
			<user-service>
				<user name="jimi" password="jimis" authorities="ROLE_USER, ROLE_ADMIN" />
				<user name="bob" password="bobs" authorities="ROLE_USER" />
			</user-service>
		</authentication-provider>
	</authentication-manager>

</beans:beans>


## /index.jsp
<h1>¸ÞÀÎ ÆäÀÌÁö</h1>
<br/>
<a href="/admin">°ü¸®ÀÚ ÆäÀÌÁö</a>


## /admin/index.jsp
<h1>Admin Main Page</h1>
Administrator only!!!
<br/>
<a href="/">¸ÞÀÎ ÆäÀÌÁö</a>


###############################################################
## ÀÀ¿ë #1 Á÷Á¢ ¸¸µç ·Î±×ÀÎ Æû

## applicationContext-security.xml
		<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
		<form-login login-page="/login.jsp"/>


## login.jsp
<h1>·Î±×ÀÎ ÆäÀÌÁö</h1>
<form name='f' action='/j_spring_security_check' method='POST'>
 <table border="1">
    <tr><td>¾ÆÀÌµð </td><td><input type='text' name='j_username' value=''></td></tr>
    <tr><td>ºñ¹Ð¹øÈ£ </td><td><input type='password' name='j_password'/></td></tr>
    <tr><td colspan='2'><input name="submit" type="submit" value="·Î±×ÀÎ"/></td></tr>
  </table>
</form>


###############################################################
## ÀÀ¿ë #2 ·Î±×¾Æ¿ô

## /index.jsp
<br/>
<a href="/j_spring_security_logout">·Î±×¾Æ¿ô</a>


###############################################################
## ÀÀ¿ë #3 »ç¿ëÀÚ ·Î±×ÀÎ È®ÀÎ

## index.jsp
<%@page import="org.springframework.security.core.*"%>
<%@page import="org.springframework.security.core.context.*"%>
<%@page import="org.springframework.security.core.userdetails.*"%>
<%
	Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

	String username = null;
	boolean isAnonymous = true;
	if (principal instanceof UserDetails) {
		username = ((UserDetails) principal).getUsername();
		isAnonymous = false;
	} else {
		username = principal.toString();
		isAnonymous = true;
	}
%>

...

<%
	if(isAnonymous) {
%>
<a href="/login.jsp">·Î±×ÀÎ</a>
<%
	} else {
%>
<%=username %>´Ô ¹Ý°©½À´Ï´Ù!
<br/>
<a href="/j_spring_security_logout">·Î±×¾Æ¿ô</a>
<%
	}
%>


###############################################################
## ÀÀ¿ë #4 Ä£ÀýÇÑ ¾È³»

## applicationContext-security.xml
	<http auto-config='true' access-denied-page="/noAuthorized.jsp">


## noAuthorized.jsp
<h1>Á¢±Ù ±ÇÇÑ ¾øÀ½!!</h1>
<br/>
<a href="/">¸ÞÀÎ ÆäÀÌÁö</a>


###############################################################
## ÀÀ¿ë #5 ·Î±×ÀÎ ½ÇÆÐ ¸Þ½ÃÁö

## applicationContext-security.xml
		<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error"/>


## login.jsp
<%@page import="org.springframework.security.core.*"%>
<%@page import="org.springframework.security.web.authentication.*"%>
<%
	boolean loginError = request.getParameter("login_error") != null;

	String errorMsg = "none";
	if (loginError) {
		AuthenticationException ex = (AuthenticationException) session.getAttribute(AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY);
		errorMsg = ex != null ? ex.getMessage() : "none";
	}
%>

...

<%
	if(loginError) {
		if("Bad credentials".equals(errorMsg)) {
%>
<font color="red">¾ÆÀÌµð³ª ºñ¹Ð¹øÈ£ ÀÔ·ÂÀÌ Æ²·È½À´Ï´Ù.</font>
<%
		} else {
%> 
<font color="red">·Î±×ÀÎ ¿¡·¯ : <%=errorMsg %></font>
<%
		}
	}
%> 


###############################################################
## ÀÀ¿ë #6 ·Î±×ÀÎ ¼º°ø ÆäÀÌÁö

## applicationContext-security.xml
		<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error"
			default-target-url="/" always-use-default-target="true"/>


###############################################################
## ÀÀ¿ë #7 Æ¯Á¤ URL Åë°ú½ÃÅ°±â

## applicationContext-security.xml
		<intercept-url pattern="/login.jsp" filters="none"/>
		<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
		<intercept-url pattern="/**" access="ROLE_USER" />
		<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error"
			default-target-url="/" always-use-default-target="true"/>


###############################################################
## ÀÀ¿ë #8-1 µ¿½Ã¿¡ 1¸í¸¸ Á¢¼Ó(±âÁ¸ ¼¼¼Ç ¸¸·á)

## applicationContext-security.xml
		<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error"
			default-target-url="/" always-use-default-target="true"/>
		<session-management>
			<concurrency-control max-sessions="1"/>
		</session-management>


###############################################################
## ÀÀ¿ë #8-2 µ¿½Ã¿¡ 1¸í¸¸ Á¢¼Ó(·Î±×ÀÎ ¿¡·¯)

## applicationContext-security.xml
		<session-management>
			<concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
		</session-management>


###############################################################
## ÀÀ¿ë #9 »ç¿ëÀÚ Á¤º¸ DB¿¡¼­ °¡Á®¿À±â

## postgresql-8.4-701.jdbc4.jar
## org.springframework.jdbc-3.0.1.RELEASE-A.jar


## db
  create table users(
      username varchar(50) not null primary key,
      password varchar(50) not null,
      enabled boolean not null);

  create table authorities (
      username varchar(50) not null,
      authority varchar(50) not null,
      constraint fk_authorities_users foreign key(username) references users(username));
      create unique index ix_auth_username on authorities (username,authority);

INSERT INTO users(username, "password", enabled) VALUES ('bob', 'bobs', true);
INSERT INTO users(username, "password", enabled) VALUES ('jimi', 'jimis', true);

INSERT INTO authorities(username, authority) VALUES ('bob', 'ROLE_USER');
INSERT INTO authorities(username, authority) VALUES ('jimi', 'ROLE_USER');
INSERT INTO authorities(username, authority) VALUES ('jimi', 'ROLE_ADMIN');


## applicationContext-security.xml
	<authentication-manager>
		<authentication-provider>
			<jdbc-user-service data-source-ref="securityDataSource" />
		</authentication-provider>
	</authentication-manager>

..

	<beans:bean id="securityDataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<beans:property name="driverClassName" value="org.postgresql.Driver" />
		<beans:property name="url" value="jdbc:postgresql:security" />
		<beans:property name="username" value="security" />
		<beans:property name="password" value="security" />
	</beans:bean>



/** ½ÉÈ­ **/


###############################################################
## ½ÉÈ­ #1 ¸Þ¼­µå ±ÇÇÑÁ¦¾î

## com.springsource.org.aopalliance-1.0.0.jar
## com.springsource.org.aspectj.tools-1.6.6.RELEASE.jar
## com.springsource.net.sf.cglib-2.1.3.jar
## org.springframework.web.servlet-3.0.1.RELEASE-A.jar


## web.xml
    <servlet>
        <servlet-name>security</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>security</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>


## security-servlet.xml
<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:component-scan base-package="my.controller" />
	
	<context:annotation-config />

	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/view/" />
		<property name="suffix" value=".jsp" />
	</bean>

</beans>


## my.controller.MyController.java
@Controller
public class MyController {

	@RequestMapping("/mvcHello")
	public void mvcHello() {
	}
}


## WEB-INF/view/mvcHello.jsp
<h1>MVC Hello</h1>


## applicationContext-security.xml
		<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
		<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error"
			default-target-url="/" always-use-default-target="true"/>

----

## applicationContext-security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

...

	<context:component-scan base-package="my.service" />

	<global-method-security secured-annotations="enabled"/>  


## my.service.MyService.java
@Service
public class MyService {

	@Secured("ROLE_ADMIN")
	public String getSecurity() {
		return "success";
	}
}


## my.controller.MyController.java
	@Autowired MyService myService;
	
	@RequestMapping("/hasSomeSecurity")
	public void hasSomeSecurity(Model model) {
		String result = myService.getSecurity();
		model.addAttribute("result", result);
	}


## index.jsp
<a href="/hasSomeSecurity.do">º¸¾È ÆäÀÌÁö</a>
<br/>


## WEB-INF/view/hasSomeSecurity.jsp
<h1>¹«¾ð°¡ º¸¾È¿ä¼Ò¸¦ °¡Áö°í ÀÖ´Â ÆäÀÌÁö</h1>
º¸¾È°á°ú : ${result }


###############################################################
## ½ÉÈ­ #2 MyUserDeatilsService

## applicationContext-security.xml
	<authentication-manager>
		<authentication-provider user-service-ref="myUserDetailsService"/>
	</authentication-manager>

	<beans:bean id="myUserDetailsService"
		class="my.service.MyUserDetailsService">
		<beans:property name="myDao">
			<beans:bean class="my.dao.MyDao">
				<beans:property name="dataSource" ref="securityDataSource"/>
			</beans:bean>
		</beans:property>
	</beans:bean>


## my.domain.MyUserDetails
public class MyUserDetails implements UserDetails {

	private String username;
	private String password;
	private boolean isEnabled = true;
	private boolean isAccountNonExpired = true;
	private boolean isAccountNonLocked = true;
	private boolean isCredentialsNonExpired = true;
	private Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
	
	public MyUserDetails(String username, String password) {
		this.username = username;
		this.password = password;
	}
	
	@Override
	public Collection<GrantedAuthority> getAuthorities() {
		return authorities;
	}

	@Override
	public String getPassword() {
		return password;
	}

	@Override
	public String getUsername() {
		return username;
	}

	@Override
	public boolean isAccountNonExpired() {
		return isAccountNonExpired;
	}

	@Override
	public boolean isAccountNonLocked() {
		return isAccountNonLocked;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return isCredentialsNonExpired;
	}

	@Override
	public boolean isEnabled() {
		return isEnabled;
	}

}


## my.service.MyUserDetailsService
public class MyUserDetailsService implements UserDetailsService {

	private MyDao myDao;
	
	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		UserDetails userDetails = myDao.getUserDetails(username);
		Collection<GrantedAuthority> authorities = myDao.getAuthorities(username);
		userDetails.getAuthorities().addAll(authorities);
		
		return userDetails;
	}

	public void setMyDao(MyDao myDao) {
		this.myDao = myDao;
	}
	
}


## my.dao.MyDao.java
public class MyDao extends JdbcDaoSupport {

    public static final String DEF_USERS_BY_USERNAME_QUERY =
        "select username,password " +
        "from users " +
        "where username = ?";
    public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY =
        "select username,authority " +
        "from authorities " +
        "where username = ?";
    
	public UserDetails getUserDetails(String username) {
        List<UserDetails> userDetailsList = getJdbcTemplate().query(DEF_USERS_BY_USERNAME_QUERY, new String[] {username}, new RowMapper<UserDetails>() {
            public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
                String username = rs.getString(1);
                String password = rs.getString(2);
                return new MyUserDetails(username, password);
            }

        });
        
        if(userDetailsList.size() == 1)
        	return userDetailsList.get(0);
        else 
        	return null;
	}

	public Collection<GrantedAuthority> getAuthorities(String username) {
        return getJdbcTemplate().query(DEF_AUTHORITIES_BY_USERNAME_QUERY, new String[] {username}, new RowMapper<GrantedAuthority>() {
            public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
                String roleName = rs.getString(2);
                return new GrantedAuthorityImpl(roleName);
            }
        });
	}

}


###############################################################
## ½ÉÈ­ #3 XML-Based Configuration

## applicationContext-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
	xmlns:sec="http://www.springframework.org/schema/security"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
		<sec:filter-chain-map path-type="ant">
			<sec:filter-chain pattern="/login.jsp" filters="none"/>		
			<sec:filter-chain pattern="/sessionExpired.jsp" filters="none"/>		
			<sec:filter-chain pattern="/**" filters="
			      securityContextPersistenceFilter,
			      logoutFilter,
			      formLoginFilter,
			      exceptionTranslationFilter,
			      filterSecurityInterceptor" />
		</sec:filter-chain-map>
	</bean>

	<bean id="securityContextPersistenceFilter"
		class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
		<property name="securityContextRepository">
			<bean class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>
		</property>
	</bean>
	
	<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
		<constructor-arg><bean class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler"/></constructor-arg>
		<constructor-arg><bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/></constructor-arg>
		<property name="filterProcessesUrl" value="/j_spring_security_logout"></property>
	</bean>

	<bean id="formLoginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
		<property name="authenticationManager" ref="authenticationManager"/>
		<property name="filterProcessesUrl" value="/j_spring_security_check"/>
		<property name="authenticationSuccessHandler">
			<bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
				<property name="defaultTargetUrl" value="/"></property>
				<property name="alwaysUseDefaultTargetUrl" value="true"></property>
			</bean>
		</property>
		<property name="authenticationFailureHandler">
			<bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
				<property name="defaultFailureUrl" value="/login.jsp?login_error"></property>
			</bean>
		</property>
		<property name="sessionAuthenticationStrategy">
			<bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
				<constructor-arg>
					<bean class="org.springframework.security.core.session.SessionRegistryImpl"></bean>
				</constructor-arg>
				<property name="maximumSessions" value="1"></property>
			</bean>
		</property>
	</bean> 

	<bean id="exceptionTranslationFilter"
	     class="org.springframework.security.web.access.ExceptionTranslationFilter">
		<property name="authenticationEntryPoint">
			<bean class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
				<property name="loginFormUrl" value="/login.jsp"/>
			</bean>
		</property>
		<property name="accessDeniedHandler">
			<bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
				<property name="errorPage" value="/noAuthorized.jsp"/>
			</bean>
		</property>
	</bean>

	<bean id="filterSecurityInterceptor"
	        class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
		<property name="authenticationManager" ref="authenticationManager"/>
		<property name="accessDecisionManager" ref="accessDecisionManager"/>
		<property name="securityMetadataSource">
			<sec:filter-security-metadata-source>
				<sec:intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
				<sec:intercept-url pattern="/**" access="ROLE_USER" />
			</sec:filter-security-metadata-source>
		</property>
	</bean>

	<bean id="authenticationManager"
		class="org.springframework.security.authentication.ProviderManager">
		<property name="providers">
			<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
				<property name="userDetailsService" ref="myUserDetailsService" />
			</bean>
		</property>
	</bean>
	
	<bean id="myUserDetailsService"
		class="my.service.MyUserDetailsService">
		<property name="myDao">
			<bean class="my.dao.MyDao">
				<property name="dataSource" ref="securityDataSource"/>
			</bean>
		</property>
	</bean>

	<bean id="securityDataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="org.postgresql.Driver" />
		<property name="url" value="jdbc:postgresql:security" />
		<property name="username" value="security" />
		<property name="password" value="security" />
	</bean>

	<bean id="accessDecisionManager" class="org.springframework.security.access.vote.ConsensusBased">
		<property name="decisionVoters">
			<list>
				<bean class="org.springframework.security.access.vote.RoleVoter"></bean>
			</list>
		</property>
	</bean>

	<context:component-scan base-package="my.service" />

	<sec:global-method-security secured-annotations="enabled"></sec:global-method-security>  
	
</beans>






