Coding/Back - Spring Framework

Spring Security : Authentication 1/2 #Day24

꿀딴지- 2023. 10. 26. 09:52

Spring Security 개요 

Spring MVC 기반 애플리케이션의 인증(Authentication)과 인가(Authorization) 기능을 지원하는 보안 프레임워크로써, Spring MVC 기반 애플리케이션에 보안을 적용하기 위한 사실상의 표준

  • 다양한 유형(폼 로그인 인증, 토큰 기반 인증, OAuth 2 기반 인증, LDAP 인증)의 사용자 인증 기능 적용
  • 애플리케이션 사용자의 역할(Role)에 따른 권한 레벨 적용
  • 애플리케이션에서 제공하는 리소스에 대한 접근 제어
  • 민감한 정보에 대한 데이터 암호화
  • SSL 적용
  • 일반적으로 알려진 웹 보안 공격 차단
  • 이 외에도 SSO, 클라이언트 인증서 기반 인증, 메서드 보안, 접근 제어 목록(Access Control List) 같은 보안을 위한 기능들을 지원

Spring Security Architecture 는 Dispatcher Servlet 전 Filter 단에서 처리되며, 3가지로 구성됨

delegatingFilterProxy(Bean Filter)

  • (계층) securityFilterChain : usernamePassword authenticationFilter token → authenticationManager → success/Failure : SecurityContextHolder에 인증객체가 담김
  • Security Context Holder 구조
    • principal(주체) : 인증된 객체 자체
    • Credentials(인증) : 자격증명 - 인증되고 나서 삭제되도 무방한 정보
    • Authorities(인가) : 권한

 

Spring Security 사용

1. Spring dependency 추가

  • dependency 추가 만으로 로그인 화면 구성됨 → custom 필수
  • 디폴트 로그인 정보 : user - 구동시 콘솔에서 pw 확인
dependencies { ...
	//Spring Security
	implementation 'org.springframework.boot:spring-boot-starter-security'
}

 

2. Spring Security Configuration 적용

  • spring의 환경설정은 configuration에서 시작됨
  • User - Role - Privilege 간의 연관관계 설정

1) SecurityFilterChain Bean 등록 : 클래스명 WebSecurityConfig , SecurityConfiguration

  • and() : Spring Security 보안 설정을 메서드 체인 형태로 구성
  • formLogin() : 기본적인 인증 방법을 폼 로그인 방식으로 지정(UsernamePasswordAuthenticationFilter의 인증방식 중 하나로 httpbasic() 등이 있음
  • longin 설정
    • loginPage("/auths/login-form") : 커스텀 로그인 페이지를 사용하도록 설정
    • loginProcessingUrl("/process_login") : 메서드를 통해 로그인 인증 요청을 수행할 요청 URL을 지정
      • loginProcessingUrl()의 파라미터인 "/process_login"은 login.html에서 form 태그의 action 속성에 지정한 URL과 동일
    • failureUrl("/auths/login-form?error") : 로그인 인증에 실패할 경우 리다이렉트 할 화면지정
  • 권한설정
    • 모두 허용 : authorizeHttpRequests().anyRequest().permitAll() : 인증에 성공할 경우 모든 권한 부여
    • 권한 제한 : authorizeHttpRequests(authorize -> authorize.antMatchers...) : 란다 표현식으로 request URI에 대한 접근 권한 부여
    ⭐ antMatchers()를 이용한 접근 권한 부여 시, 주의 사항
  • request URL 설정 오류를 방지하기 위해 항상 더 구체적인 URL 경로부터 접근 권한을 부여한 다음 덜 구체적인 URL 경로에 접근 권한을 부여할 것.
@Configuration
public class SecurityConfiguration {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
						.headers().frameOptions().sameOrigin() // 개발에서 H2 웹 콘솔을 사용하기 위해 보안 옵션 해제, Clickjacking 공격에 취약
            .and()
            .csrf().disable()                 
            .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()                    
            );

            //.and()                                   
            //.authorizeHttpRequests()                     
            //.anyRequest().permitAll();                           

        return http.build();
    }
	
		// 인메모리DB에 사용자 추가 
		@Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user =
                User.withDefaultPasswordEncoder()
                        .username("kevin@gmail.com")
                        .password("1111")
                        .roles("USER")
                        .build();

        // admin 권한 유저
        UserDetails admin =
                User.withDefaultPasswordEncoder()
                        .username("admin@gmail.com")
                        .password("2222")
                        .roles("ADMIN")
                        .build();

        return new InMemoryUserDetailsManager(user, admin);
    }
}

2) PasswordEncoder Bean 등록

  • Spring Security에서 제공하는 패스워드 암호화 기능을 제공하는 컴포넌트
  • PasswordEncoder : 다양한 암호화 방식을 제공하며, Spring Security에서 지원하는 디폴트 암호화 알고리즘은 bcrypt

3. Spring Security에서 관리하는 User Class 구현체 구현

1) Entity implements UserDetails

  • Spring Security에서 관리하는 User 정보를 UserDetails로 관리
  • UserDetails는 UserDetailsService에 의해 로드(load)되어 인증을 위해 사용되는 핵심 User 정보를 표현하는 인터페이스
  • UserDetails 인터페이스의 구현체는 Spring Security에서 보안 정보 제공을 목적으로 직접 사용되지는 않고, Authentication 객체로 캡슐화되어 제공

2) Service implements UserDetailsService

  • Spring Security에서 User 정보를 로드(load)하는 핵심 인터페이스
  • 여기서 로드(load)의 의미는 인증에 필요한 User 정보를 어딘가에서 가지고 온다는 의미이며, 여기서 말하는 ‘어딘가’는 메모리가 될 수도 있고, DB 등의 영구 저장소가 될 수도 있음