Spring Security | Spring Security이란? | Java Configuration
Spring Security 3.2에서는 Spring 3.1에 추가된 Java Configuration 사용할 수 있도록 되어있다. Java Configuration을 사용하면 XML 파일 없이도 namespace과 같은 설정을 작성할 수 있다.
Java Configuration을 사용하면 어느 정도의 설정 오류는 컴파일러가 체크 해주고, 리팩토링이 용이해진다는 장점이 있다.
Hello World를 Java Configuration에서 대체하기
.
├── build.gradle
└── src
└── main
├── java
│ └── sample
│ └── spring
│ └── security
│ └── MySpringSecurityConfig.java
└── webapp
├── WEB-INF
│ └── web.xml
└── index.jsp
컨테이너의 구현
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<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>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>sample.spring.security.MySpringSecurityConfig</param-value>
</context-param>
</web-app>
기본적으로 사용된 XmlWebApplicationContext 대신에 AnnotationConfigWebApplicationContext를 사용하도록 설정을 변경한다.
contextClass라는 이름으로 <context-param>
을 정의하면, ContextLoaderListener는 거기에서 지정한 클래스를 컨테이너로 이용하게 된다.
또한 AnnotationConfigWebApplicationContext가 로드하는 설정 클래스는 contextConfigLocation이라는 이름으로 <context-param>
을 정의하여 지정할 수 있다.
src/main/java/sample/spring/security/MySpringSecurityConfig.java
package sample.spring.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;
@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin();
}
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("devkuma").password("1234").roles("USER");
}
}
Spring Security를 활성화하기
Spring Security의 Java Configuration을 사용하려면 AnnotationConfigWebApplicationContext에서 로드한 클래스를 @EnableWebSecurity
으로 어노테이션을 지정한다.
왜 이것으로 Spring Security가 활성화되는지는 이 어노테이션의 구현을 보면 알 수 있다. 구현된 내용은 아래와 같다.
EnableWebSecurity.java
...
package org.springframework.security.config.annotation.web.configuration;
...
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
...
@Import({ WebSecurityConfiguration.class,
SpringWebMvcImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
...
}
@Import
를 사용하여 WebSecurityConfiguration가 로드되고 있다. 이 클래스도 @Configuration
어노테이션이 부여된 설정 클래스가 있다.
Spring Security의 설정
Spring Security의 구체적인 설정을 해가지 위해, 먼저 WebSecurityConfigurerAdapter라는 클래스를 상속한다.
WebSecurityConfigurerAdapter는 디폴트로 간단한 SecurityFilterChain을 구축하게 된다. 이 클래스를 상속하고 configure (HttpSecurity) 등의 메소드를 오버라이드하여 구축되는 SecurityFilterChain을 임의로 정의할 수 있다.
인수 받을 HttpSecurity가 namespace에서의 <http>
태그에 대응된다. 기본적으로 <http>
에 있는 설정은 HttpSecurity으로 가능하게 되어 있다.
위의 구현은 다음 XML과 같은 의미가 된다.
(※ 로그 아웃은 WebSecurityConfigurerAdapter가 내부에서 자동으로 등록하고 있기 때문에 생략하고 있다.)
applicaitonContext.xml
<sec:http>
<sec:intercept-url pattern="/login" access="permitAll" />
<sec:intercept-url pattern="/**" access="isAuthenticated()" />
<sec:form-login />
<sec:logout />
</sec:http>
authorizeRequests()
메소드는 namespace에서의 <intercept-url>
의 설정을 시작하는 메소드가 된다.
메소드의 반환 값의 형태가 ExpressionInterceptUrlRegistry라는 클래스가 되고, 전용 설정 메소드가 부를 수 있게 되어 있다.
<intercept-url>
의 설정을 종료시켜 다른 설정을 계속하려면, and()
메소드를 이용한다.
and()
메소드는 HttpSecurity를 반환하므로, 메소드 체인을 중단시키지 않으면서 다음 설정을 계속할 수 있다.
formLogin()
는 이름 그대로 Form 인증으로 사용한다.
사용자 정보 설정
AuthenticationManagerBuilder는 AuthenticationManager의 클래스를 정의하기 위한 지원 클래스로 위에 구현처럼 메소드 체인을 사용하여 UserDetailsService 등을 정의할 수 있다.
혹은 AuthenticationManagerBuilder를 사용하지 않고 직접 Bean을 정의하는 메소드를 선언할 수도 있다.
Bean정의로 설정을 하는 경우
package sample.spring.security;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
...
@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
...
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("hoge").password("HOGE").roles("USER").build());
return manager;
}
}