[java] 스프링 시큐리티와 서블릿 3.0 인증

스프링 시큐리티(Spring Security)는 자바 기반 애플리케이션의 보안을 강화하기 위한 프레임워크입니다. 서블릿 3.0은 자바 애플리케이션의 웹 프로그래밍 모델을 정의하는 스팩입니다. 스프링 시큐리티와 서블릿 3.0을 함께 사용하면 애플리케이션의 인증 기능을 효과적으로 구현할 수 있습니다.

스프링 시큐리티 설정

스프링 시큐리티를 사용하기 위해서는 먼저 스프링 시큐리티의 의존성을 추가해야 합니다. Maven을 사용하는 경우, pom.xml 파일에 다음과 같이 의존성을 추가합니다:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

스프링 부트를 사용하는 경우, 스프링 시큐리티의 기본 설정은 자동으로 활성화됩니다. 그러나 스프링 부트를 사용하지 않는다면, 설정 파일에 다음과 같이 스프링 시큐리티 설정을 추가해야 합니다:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }
}

위의 설정은 모든 요청을 인증된 사용자만 접근할 수 있도록 구성합니다. /public/**로 시작하는 경로는 인증없이 접근이 가능하며, /login 경로는 로그인 페이지로 사용됩니다.

서블릿 3.0 인증

서블릿 3.0은 서블릿 컨테이너가 자동으로 인증을 처리하는 기능을 제공합니다. 위에서 작성한 스프링 시큐리티의 설정과 함께 서블릿 3.0 인증을 사용하려면, web.xml 파일에 다음과 같이 설정을 추가해야 합니다:

<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/login</form-login-page>
        <form-error-page>/login?error</form-error-page>
    </form-login-config>
</login-config>

위의 설정은 /login 경로를 로그인 페이지로 사용하고, 인증 실패 시 /login?error 경로로 리디렉션합니다.

인증 커스터마이징

스프링 시큐리티를 사용하면 로그인 기능을 커스터마이징할 수 있습니다. 예를 들어, 사용자 정의 인증 로직을 구현하려면 UserDetailsService 인터페이스를 구현하고 로그인 페이지에서 받은 사용자 정보를 이용하여 사용자를 인증할 수 있습니다:

@Service
public class CustomUserDetailsService implements UserDetailsService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        
        if (user == null) {
            throw new UsernameNotFoundException("Invalid username");
        }
        
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user.getRoles()));
    }
    
    private List<GrantedAuthority> getAuthorities(List<Role> roles) {
        return roles.stream()
                .map(role -> new SimpleGrantedAuthority(role.getName()))
                .collect(Collectors.toList());
    }
}

위의 코드에서 UserDetailsService의 구현체는 UserRepository를 사용하여 사용자를 찾은 후, UserDetails 객체를 반환합니다. 이렇게 구현한 UserDetailsService를 스프링 시큐리티 설정에서 사용하도록 설정해야 합니다:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private CustomUserDetailsService userDetailsService;
    
    // ...
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
}

위의 설정에서는 AuthenticationManagerBuilder를 사용하여 UserDetailsService를 설정합니다.

참고자료