본문 바로가기
부트캠프 개발일기/Spring Security

62일차: Spring Security

by shyun00 2023. 5. 12.

❯ Spring Security

Spring MVC 기반 애플리케이션의 인증(Authentication)과 인가(Authorization)를 지원하는 보안 프레임워크이다.

Spring Security를 통해 다양한 유형(폼 로그인 인증, 토큰 기반 인증, OAuth 2 기반 인증 등)의 사용자 인증 기능을 적용할 수 있고

애플리케이션 사용자 Role따라 권한을 다르게 적용할 수 있으며 데이터 암호화, SSL적용 등을 할 수 있다.

<관련 용어>

  • Principal(주체): 애플리케이션에서 작업을 수행할 수 있는 사용자, 시스템 등을 의미하며 일반적으로 인증된 사용자 계정 정보를 의미함
  • Authentication(인증): 사용자 본인이 맞음을 증명하는 절차를 의미함. 사용자 식별을 위한 정보를 Credential(신원 증명 정보)이라함
  • Authorization(인가): 인증이 정상적으로 완료된 사용자에게 권한을 부여해 특정 리소스에 접근하게 하는것
  • Access Control(접근 제어): 사용자가 애플리케이션의 리소스에 접근하는 행위를 제어하는것

Spring Security Configuration

Spring Security Configuration을 통해 우리가 원하는 인증 방식과 웹페이지에 대한 접근 권한을 설정할 수 있다.

Configuration 클래스에 Spring Security에서 지원하는 인증과 권한 부여 설정을 하면 된다.

 

1. Spring Security에서는 사용자의 정보를 포함한 UserDetails 클래스를 지원하며 이를 관리하는 UserDetailsManager 인터페이스를 제공한다.

[UserDetailsManager 인터페이스 코드]

public interface UserDetailsManager extends UserDetailsService {

   /**
    * Create a new user with the supplied details.
    */
   void createUser(UserDetails user);

   /**
    * Update the specified user.
    */
   void updateUser(UserDetails user);

   /**
    * Remove the user with the given login name from the system.
    */
   void deleteUser(String username);

   /**
    * Modify the current user's password. This should change the user's password in the
    * persistent user repository (datbase, LDAP etc).
    * @param oldPassword current password (for re-authentication if required)
    * @param newPassword the password to change to
    */
   void changePassword(String oldPassword, String newPassword);

   /**
    * Check if a user with the supplied login name exists in the system.
    */
   boolean userExists(String username);

}

 

2. HttpSecurity를 통해 HTTP 요청에 대한 보안 설정을 구성할 수 있다.

HttpSecurity를 파라미터로 가지고 SecurityFilterChain을 리턴하는 메서드를 통해 HTTP 보안 설정을 구성할 수 있다.

antMatchers()를 통해 URL 경로별 접근 권한을 부여할 수 있는데, 구체적인 경로에서부터 덜 구체적인 경로로 접근 권한을 부여해야 정상적으로 적용된다. (코드는 순차적으로 수행되기 때문)

[코드 예시]

@Configuration
public class SecurityConfiguration {

    // HTTP 보안 구성
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    
        http.csrf().disable() // 로컬에서 테스트 예정이므로 csrf 비활성화
                .formLogin()
                .loginPage("/auths/login-form")
                .loginProcessingUrl("/process_login")
                .failureUrl("/auths/login-form?error")
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/")
                .and()
                .exceptionHandling().accessDeniedPage("/auths/access-denied")
                .and()
                .authorizeHttpRequests(authorize -> authorize
                        .antMatchers("/orders/**").hasRole("ADMIN")
                        .antMatchers("/members/my-page").hasRole("USER")
                        .antMatchers("/**").permitAll()
                );

        return http.build();
    }
}

데이터베이스 연동 없는 로그인 인증(회원가입) 구현하기 (폼로그인 방식 사용)

회원가입 폼을 통해서 InMemory User 등록하기

1. PasswordEncoder Bean 등록: 회원가입 폼을 통해 전달받은 패스워드를 인메모리DB에 등록하기 전에 암호화한다.

    Spring Security에서 지원하는 PasswordEncoder의 디폴트 암호화 알고리즘은 bcrypt임.

2. Service Bean 등록을 위한 Configuration 구성: 실제 회원가입 비즈니스 로직을 담당하는 Service 클래스를 @Bean으로 등록한다.

3. Service 클래스 구현: UserDetailsManager와 PasswordEncoder를 DI받아서 비밀번호를 암호화하고 권한을 부여한 뒤 해당 userDetails를 바탕으로 회원가입을 구현한다. * UserDetails: Spring Security에서 관리하는 User 정보

데이터베이스 연동을 통한 로그인 인증(회원가입) 구현하기

User의 인증정보를 테이블에 저장하고, 저장된 인증정보를 통해 인증 프로세스를 진행할 수 있다. 

 

<Custom UserDetailsService 이용>

그 중 한가지 방법이 Custom UserDetailsService를 이용하는 것이다.

1. SecurityConfiguration 설정: 위에서 설정한 파일과 유사함.

2. JavaConfiguration 설정: Repository와 PasswordEncoder를 DI받은 서비스 클래스를 Bean으로 등록

3. Service 클래스 구현: 입력받은 회원정보의 비밀번호를 암호화하고 Repository에 저장

4. Custom UserDetailsService 구현: DB에서 조회한 User의 인증 정보를 기반으로 인증을 처리하는 객체.
    UserDetailsService는 User 정보를 로드하는 인터페이스를 말한다. UserDetailsService를 구현하는 객체를 정의한다.

    User 클래스의 객체를 리턴하면 Spring Security가 정보를 이용해 인증 절차를 수행해준다.

5. 권한(Role)을 DB에서 관리하기: 권한 정보를 저장하기 위한 테이블을 생성하고 권한 정보를 DB에 저장, 로그인 인증 시 조회할 수 있도록 한다. List, Set과 같은 컬렉션 타입의 필드는 @ElementCollection 애너테이션을 통해 별도의 엔티티 클래스 생성 없이도 테이블을 생성, 매핑할 수 있다.

 

<Custom AuthenticationProvider 이용>

Custom AuthenticationProvider를 이용하면 직접 로그인 인증을 처리할 수 있다.

(Custom UserDetailsService를 이용하는것은 Spring Security가 내부적으로 인증을 처리해주는 방식임)

1. Custom AuthenticationProvider는 AuthenticationProvider를 구현하는 클래스로 정의한다.
    Spring Security는 AuthenticationProvider를 구현한 클래스가 Spring Bean으로 등록되어있다면
    해당 AuthenticationProvider를 이용해서 인증을 진행한다.

 

    AuthenticationProvider인터페이스에는 아래 두가지 메서드가 포함되어있다.

Authentication authenticate(Authentication authentication) throws AuthenticationException;
boolean supports(Class<?> authentication);

한가지 주의해야할 사항은 Custom AuthenticationProvider 에서 AuthenticationException이 아닌 다른 Exception이 발생할 경우에는 꼭 AuthenticationException을 rethrow하도록 코드를 구성해야한다.


갑자기 난이도가 많이 어려워진 느낌을 받았다. 위 글에는 작성하지 않았지만 코드 실습하는 부분이 있었는데 해당 부분이 많이 복잡하게 느껴졌다. 아무래도 반복 학습을 여러번 해야할것같다.