Clean Code that Works.


스프링 버전 : 4.0.0.RELEASE
스프링 시큐리티 버전 : 3.2.5.RELEASE

아직 root-context를 xml 설정을 사용하고 있어 시큐리티 부터 java config를 사용하기 위해 시작.

스프링 시큐리티 java config 링크

3년전만해도 스프링 시큐리티 문서 진짜 부족한게 많았는데.. 
이렇게 좋아 지다니.. 놀랍구나.

기존 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.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <global-method-security pre-post-annotations="enabled" />
    <http use-expressions="true" authentication-manager-ref="authManager">
        <intercept-url pattern="/index.jsp" access="permitAll" />
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/home" access="permitAll" />
        <intercept-url pattern="/favicon.ico" access="permitAll" />
        <intercept-url pattern="/resources/**" access="permitAll" />
        <intercept-url pattern="/publish/**" access="permitAll" />

        <intercept-url pattern="/j_spring_security_logout" access="isAuthenticated()" />

        <intercept-url pattern="/user/updateUser" access="isAuthenticated()" />
        <intercept-url pattern="/user/info" access="isAuthenticated()" />

        <intercept-url pattern="/login/**" access="isAuthenticated()" />

        <intercept-url pattern="/gas/**" access="isAuthenticated()" />
        <intercept-url pattern="/payment/**" access="isAuthenticated()" />
        <intercept-url pattern="/etc/**" access="isAuthenticated()" />
        <intercept-url pattern="/stats/**" access="isAuthenticated()" />

        <intercept-url pattern="/secure/**" access="isAuthenticated()" />
        <intercept-url pattern="/manage/**" access="hasRole('ROLE_ADMIN')" />
        <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
        <intercept-url pattern="/comment/admin/**" access="hasRole('ROLE_ADMIN')" />

        <form-login login-page="/user/loginForm"    authentication-success-handler-ref="loginSuccessHandler" />

        <logout logout-url="/logout" logout-success-url="/home" />
    </http>

    <authentication-manager id="authManager">
        <authentication-provider user-service-ref="userDetailService">
            <password-encoder ref="passwordEncoder" />
        </authentication-provider>
    </authentication-manager>
</beans:beans>

거의 기본 설정이라서 아주 심플하다. 
딱히 특별한것도 없음..;

Java Config로 설정

@Configuration @EnableWebSecurity public class SecurityWebApplicationInitializer extends WebSecurityConfigurerAdapter { @Autowired private UserDetailService userDetailService; @Autowired private LoginSuccessHandler loginSuccessHandler; @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/index.jsp", "/home", "/favicon.ico", "/resources/**", "/publish/**").permitAll() .antMatchers("/secure/**", "/manage/**", "/admin/**", "/comment/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin() .loginPage("/user/loginForm") .loginProcessingUrl("/j_spring_security_check") .usernameParameter("j_username") .passwordParameter("j_password") .successHandler(loginSuccessHandler) .permitAll() .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/home") .and() .csrf().disable() .httpBasic(); } @Override protected UserDetailsService userDetailsService() { return userDetailService; } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }

위에 링크해둔 스프링 시큐리티 java config 문서에도 친절하게 설명이 잘 나와 있다.
문서 보면서 천천히 해보면 더 좋을 듯.

딱히 특별한건 없고 xml 설정에서 사용하던 authentication-manager를 사용하기 위해서 configre(AuthenticationmanagerBuilder auth)를 세팅했다.

.formLogin() 부분에 보면 processingUrl이랑 username, password 파라미터를 세팅하도록 되어 있는데 이게 원래 기본으로 설정되어 있던거였는데 안되더라..

HttpSecurity.java 의 formLogin()을 보면 FormLoginConfigurer를 사용하는데 여기서 사용하는 default 값이 "username", "password" 이 두가지로 세팅되어 있다.
UsernamePasswordAuthenticationFilter.java 에선 여전히 "j_username", "j_password"를 사용하고 있어서 위처럼 값을 세팅해줘야 사용 가능하다.

그리고 .csrf() 이 설정은 CSRF 공격을 막기위해 세팅되어있는데 .disable()을 세팅해 놓지 않으면 해당 작업을 수행하기 위한 파라미터가 없다고 에러가 발생하기 때문에 .disable()을 해주도록 한다.

csrf().disable()을 안해주면 만나는 에러 
HTTP Status 403 - Expected CSRF token not found. Has your session expired?

이렇게 설정을 바꿈으로서 xml 설정보다 코드를 약간 더 줄일 수 있었고, 조금더 읽기 쉬운 코드가 됬다.