스프링 시큐리티
- 의미 : 스프링 기반의 애플리케이션 보안(인증, 인가, 권한)을 담당하는 스프링 하위 프레임워크로, 필터 기반으로 동작한다.
- CSRF 공격, 세션 고정 공격을 방어해주고, 요청 헤더도 보안 처리를 해주므로 개발자가 보안 관련 개발을 해야 하는 부담을 줄여준다.

 

 

 

Domain 패키지

@Table(name = "users")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class User implements UserDetails{ //UserDetails를 상속받아 인증 객체로 사용

	...
    
    @Builder
    public User(String email, String password, String auth){
    	this.email = email;
        this.password = password;
    }
    
    ...
}

▶ User 클래스가 상속한 UserDetails 클래스는 스프링 시큐리티에서 사용자의 인증 정보를 담아 두는 인터페이스, 

스프링 시큐리티에서 해당 객체를 통해 인증 정보를 가져오려면 필수 오버라이드 메서드들을 여러 개 사용해야 한다.

 

 

Repository 패키지

public interface UserRepository extends JpaRepository<User, Long>{
	Optional<User> findByEmail(String email); //email로 사용자 정보를 가져옴
}

▶ 이메일로 사용자를 식별할 수 있다. 

▶ findByEmail() : FROM user WHERE email = #{email}

 

 

Service 패키지

@RequiredArgsConstructor
@Service
public class UserDetailService implements UserDetailsService{
	private final UserRepository userRepository;
    
    //사용자 이름(email)으로 사용자의 정보를 가져오는 메서드
    @Override
    public User loadUserByUsername(String email){
    	return userRepository.findByEmail(email).orElseThrow(() -> new IllegalArgumentException((email)));
    }
}

UserDetailsService 인터페이스 : 스프링 시큐리티에서 사용자 정보를 로드하기 위한 메서드를 정의한 인터페이스로, 이 인터페이스를 구현하려면 loadUserByUsername() 메서드를 반드시 구현해야 한다.

loadUserByUsername() : 주어진 사용자 이름(또는 식별자)을 기반으로 사용자 정보를 로드하는 역할을 한다.

만약, 이 메서드를 오버라이딩 하지 않는다면 스프링 시큐리티가 'UserDetailsService'를 사용할 때 해당 메서드가 적절한 사용자 정보를 로드할 수 없게 되어, 사용자 인증 및 권한 부여와 관련된 동작이 제대로 이루어지지 않아 컴파일 오류가 발생하게 된다.

 

 

Config 패키지

@RequiredArgsConstructor
@Configuration
public class WebSecurityConfig{
	
    private final UserDetailService userService;
    
    //스프링 시큐리티 기능 비활성화
    @Bean
    public WebSecurityCustomizer configure(){
    	return (web) -> web.ignoring()
        	.requestMatchers(toH2Console())
                .requestMatchers("/static/**");
    }
    
    //특정 HTTP 요청에 대한 웹 기반 보안 구성
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
    	return http
        	.authorizeHttpRequests() //인증, 인가 설정
                .requestMatchers("/login", "/signup", "/user").permitAll()
                .anyRequest().anthenticated()
                .and()
                .formLogin() //폼 기반 로그인 설정
                .loginPage("/login")
                .and()
                .logout() //로그아웃 설정
                .logoutSuccessUrl("/login")
                .invalidateHttpSession(true)
                .and()
                .csrf().disable() //csrf 비활성화
                .build();
    }
    
    //인증 관리자 관련 설정
    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http, 
    BCryptPasswordEncoder bCryptpasswordEncoder, UserDetailService userDetailService) throws Exception{
    	return http.getSharedObject(AuthenticationManagerBuilder.class)
        	.userDetailsService(userServicie)
                .passwordEncoder(bCryptPasswordEncoder)
                .and()
                .build();
    }
    
    //패스워드 인코더를 사용할 빈 등록
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
    	return new BCryptPasswordEncoder();
    }
}

 

= 메서드 부가 설명

confugrure() - static 하위 경로에 있는 리소스와 h2-console 하위 url 대상으로 스프링 시큐리티의 모든 기능(인증, 인가) 서비스를 적용하지 않음
filterChain() - 특정 Http 요청에 대한 웹 기반 보안을 구성.
- 인증, 인가 및 로그인, 로그아웃 관련 설정
authenticationManager()  - 인증 관리자 관련 설정
- 사용자 정보를 가져올 서비스를 재정의하거나, 인증 방법(JDBC 기반 인증) 등을 설정할 때 사용

 

= filterChain() 메서드 부가 설명

requestMatchers() 특정 요청과 일치하는 url에 대한 액세스를 설정
permitAll() 누구나 접근이 가능하게 설정. (/login, /signup, /user로 요청이 오면 인증,인가 없이 접근 가능
anyRequest() 위에 설정한 url 이외의 요청에 대해서 설정
authenticated() 별도의 인가는 필요하지 않지만 인증이 성공된 상태여야 접근 가능
loginPage() 로그인 페이지 경로 설정
defaultSuccessUrl() 로그인이 완료되었을 때 이동할 경로 설정
logoutSuccessUrl() 로그아웃이 완료되었을 때 이동할 경로 여부 설정
invalidateHttpSession() 로그아웃 이후에 세션을 전체 삭제할지 여부를 설정

 

 

 

+ Recent posts