[Spring] Spring Security - 로그인 사용법

이신영·2024년 4월 9일
1

Spring

목록 보기
13/16
post-thumbnail
post-custom-banner

지난번은 간단한 스프링 시큐리티의 동작과정을 알아보았다. 이번시간은 동작과정에서 로그인을 확장해서 자신의 프로젝트에 대입하는 과정을 알아보도록하자


인증 과정

UserDetailsService : 사용자 조회(R)
UserDetailsManager : 사용자 CUD
PasswordEncoder : 비밀번호 암호화

스프링 시큐리티의 인증/인가를 요약하자면 filter를 거친 다음 AuthenticationManager가 알맞은 Provider를 선택한다.UserDetailsServicePasswordEncoder를 이용한다.

암호화 걍 안해도되는거아님? 하지만 스프링 시큐리티는 암호화를 권장한다. 앵간하면 쓰도록하자 😅

이 외에도 필터와 권한설정에 대한 확장방법도 매우매우매우많다. 대부분 스프링 시큐리티가 디폴트로 처리해주는건데 여기서는 로그인 방법에 대해 알아보는걸 주로 하자..!


구현하기

이제 본격적으로 구현하기위해 UserDetailsServiceloadUserByUsername()을 커스텀해서 조회 시 UserDetails가 반환되도록 코드를 작성하면된다.

UserDetailsManager << 이건 안씀?

User는 정보가 부족하기때문에(닉네임, 주소, 나이 등등) UserDetailsManager보다 그냥 엔티티하나를 만들어쓴다. 고로 조회기능을 사용하기위해 UserDetailsService를 implement해주면된다.

webconfig 설정

@EnableWebSecurity
@Configuration
public class WebSecurityConfig {

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(authorizeRequests ->
                        authorizeRequests
                                .requestMatchers("/members/login", "/").permitAll() //정의된 주소에 접근허용
//                                .anyRequest().authenticated() // 모든 url에 접근권한이 필요함
                )
                .csrf(AbstractHttpConfigurer::disable) // csrf 토큰 사용 안함
                .formLogin(formLogin ->
                        formLogin
                                .loginPage("/members/login") //로그인 페이지 경로
                                .usernameParameter("username") //username 파라미터 명(폼에서 일치해야함)
                                .passwordParameter("password") //password 파라미터 명(폼에서 일치해야함)
                                .defaultSuccessUrl("/", true) //로그인 성공 시 Url 
                )
                .logout((logout)-> logout
                        .logoutRequestMatcher(new AntPathRequestMatcher("/members/logout")) //로그아웃 요청 경로
                        .logoutSuccessUrl("/") // 로그아웃 성공 시 Url
                        .invalidateHttpSession(true) //로그아웃 성공 시 모든 세션 삭제
                )

                ;
        return http.build();
    }

}

스프링에서는 어떠한 사전정의를 하기위해 작성하는 클래스는 보통 @Configuration을 선언한 곳에서 작성한다. 고로 webconfig에 대한 설정을 해주면된다. 여기서 주로 봐야할건

authorizeRequests : 사용자의 요청을 인증하고 권한을 부여
csrf : Cross-Site Request Forgery(CSRF) 공격을 방지하는 설정이지만 로컬스토리지를 사용하고있어서 껐음
formLogin : 폼 기반 인증 활성화
logout : 로그아웃 구성

이 네가지로 Spring Security를 설정해주었다. 이제 로그인기능인 조회를 할 수 있어야한다.

회원 조회기능(loadByUsername)

@RequiredArgsConstructor
@Service
public class MemberSecurityServiceImpl implements UserDetailsService {

    private final MemberRepository memberRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Member member = memberRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다."));

        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(member.getRole().equals(ADMIN) ? "ADMIN" : "USER"));

        return new User(member.getUsername(), member.getPassword(), authorities);
    }


}

만약 처음 로그인 구현을 무작정 따라해보면 이러한 의문이 들 수 있다.
"난 딱히 경로를 지정한 곳이 없는데 어떻게 알아서 로그인처리를 해주는거지?" 라는 생각이 들 수있는데 대부분 이런 의구심이 들때는 해당 기술에 대한 동작과정을 보는걸 추천한다. 문제점은 아마 기존에 있던 기능을 확장하는 방식으로 사용되어서 자동처리되기때문에 과정을 이해하지못한다면 알수없기때문이다!

스프링 시큐리티는 로그인 요청이 들어오면 UserDetailsServiceloadUserByUsername()을 자동으로 호출한다. 우리는 따로 DB를 사용하고있기때문에 DB에서 조회하게끔 메서드를 커스텀해야하는것이다.
UserDetails 는 인증여부를 확인하는 사용자정보 인터페이스인데 UserUserDetails를 구현한 객체이다.


스프링 시큐리티를 처음배웠을 땐 되게어렵다.. 였고 배우다보니 어 쉽네? 였고 상세하게 배우다보니 이걸 언제 다 알아가냐.. 라는 생각이다. 다 배울생각보다는 과정에 대해 알아가고 기능구현시에 확장이 필요하다면 알아가는게 좋을거같다!

profile
후회하지 않는 사람이 되자 🔥
post-custom-banner

0개의 댓글