[Spring] spring security 적용하기

yoon·2024년 3월 20일

spring-boot

목록 보기
20/41
post-thumbnail

✅Spring Security

✔ 개념

스프링 기반 애플리케이션의 보안을 담당하는 스프링 하위 프레임워크
스프링 시큐리티는 필터 기반으로 동작하며, 다양한 필터들로 나눠져 있다.
각 필터는 인증, 인가와 관련된 작업을 처리한다.

✔ 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
testImplementation 'org.springframework.security:spring-security-test'

✔ 적용하기

1. User entity 작성 > UserDetails 상속

  • UserDetails
    스프링 시큐리티에서 사용자의 인증 정보를 담아두는 인터페이스
    해당 객체를 가지고 인증 정보를 가져오려면 다음의 메서드들을 오버라이드 해야한다.
public class User implements UserDetails {
// 필요한 컬럼 작성하기
...
	@Override // 권한 반환
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return List.of(new SimpleGrantedAuthority("user"));
    }
    
     @Override
    public String getPassword() {
        return password;
    }

    @Override 
    public String getUsername(){
    	// 사용자 이름으로 사용할 컬럼을 반환해준다. ex)email
        return username;
    }

    // 계정 만료 여부 반환
    @Override
    public boolean isAccountNonExpired() {
        // 만료되었는지 확인하는 로직
        return true; //true > 만료되지 않음
    }

    // 계정 잠금 여부 반환
    @Override
    public boolean isAccountNonLocked() {
        // 계정 잠금되었는지 확인하는 로직
        return true; // true > 잠기지 않음
    }

    // 패스워드의 만료 여부 반환
    @Override
    public boolean isCredentialsNonExpired() {
        // 패스워드 만료 확인 로직
        return true; //true > 만료되지 않음
    }

    //계정 사용 가능 여부 반환
    @Override
    public boolean isEnabled() {
        // 계정 사용 가능 여부 확인 로직
        return true; // true > 사용 가능
    }
}

2. 서비스 메서드 코드

@Service
@RequiredArgsConstructor
// 스프링 시큐리티에서 사용자 정보를 가져오는 인터페이스
public class UserDetailService implements UserDetailsService {

    private final UserRepository userRepository;

    // 사용자 이름으로 사용자의 정보를 가져오는 메서드
    @Override
    public User loadUserByUsername(String username){
    // User에서 설정해준 컬럼을 넣어줘야한다. ex) email
        return userRepository.findByUsername(username)
                .orElseThrow(()->new IllegalArgumentException(username));
    }
}

3. 시큐리티 설정

주요 메서드

  • requestMatchers() : 특정 요청과 일치하는 url에 대한 액세스 설정
  • permitAll(): 누구나 접근 가능 > 인증/인가 없이 접근 가능
  • anyRequest() : requestMatchers에 설정하지 않은 url에 대한 요청
  • authenticated() : 인가는 필요없지만, 인증이 성공된 상태에 접근 가능
// 경로 > config/WebSecurityConfig
@Configuration
@RequiredArgsConstructor
public class WebSecurityConfig {
    private final UserDetailsService userService;

    // 스프링 시큐리티 기능 비활성화 > 정적 리소스
    @Bean
    public WebSecurityCustomizer configure(){
        return (web) -> web.ignoring()
                .requestMatchers(toH2Console())
                .requestMatchers("/static/**");
    }

    // 특정 http 요청에 대한 웹 기반 보안 구성
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        return http
                .authorizeRequests()//인증, 인가 설정
                .requestMatchers("/login", "/signup","/user").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin() // 폼기반 로그인 설정
                .loginPage("/login") // 설정하지 않으면 시큐리티에서 기본 제공하는 로그인 페이지로 이동
                .defaultSuccessUrl("/articles") // 로그인 성공시 이동
                .and()
                .logout()
                .logoutSuccessUrl("/login")
                .invalidateHttpSession(true) // 로그아웃 이후 세션 전체 삭제 여부 설정
                .and()
                .csrf().disable()
                .build();
    }
	//  인증 관리자 관련 설정
    @Bean 
    public AuthenticationManager authenticationManager(
            HttpSecurity http,
            BCryptPasswordEncoder bCryptPasswordEncoder,
            UserDetailsService userService
    ) throws Exception {
        return http.getSharedObject(AuthenticationManagerBuilder.class)
                .userDetailsService(userService) // 반드시 userDetailsService를 상속받은 클래스
                .passwordEncoder(bCryptPasswordEncoder)
                .and()
                .build();
    }
	//패스워드 인코더로 사용할 빈 등록
    @Bean 
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

4. 컨트롤러, 서비스 작성하기
로그인, 회원가입시 반환할 viewController와 apiController를 작성한다.

◾ 로그아웃 메서드

@GetMapping("/logout")
    public String logout(HttpServletRequest request, HttpServletResponse response){
        new SecurityContextLogoutHandler().logout(request, response, SecurityContextHolder.getContext().getAuthentication());
        return "redirect:/login";

    }

✔ security 기능 끄기

@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}
profile
하루하루 차근차근🌱

0개의 댓글