[Spring] 로그인, 로그아웃 구현

이신영·2024년 4월 9일
0

S0S

목록 보기
5/8
post-thumbnail

이제 찜 기능과 게시판 기능을 만들기 위해서 로그인정보를 구현해야 할 때가 되었다. 로그인은 Spring Security을 사용할건데 로그인과정의 자세한 내용은 여기여기에 포스팅해두었다 😀


과정 요약

SecurityfilterChainUserDetailsService를 활용하여 구현해보았다. 대략적인 과정은

  1. Webconfig 클래스 만들기
    1.1. filterChain 매서드 만들기 - 보안설정, 로그인, 로그아웃 경로 설정
    1.2. PasswordEncoder 매서드로 비밀번호 암호화
  2. UserDetailsService의 loadUserByUsername() 커스텀하기
  3. 로그인, 로그아웃 폼 만들기

로그인/로그아웃 구현

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()
                )
                .csrf(AbstractHttpConfigurer::disable)
                .formLogin(formLogin ->
                        formLogin
                                .loginPage("/members/login")
                                .usernameParameter("username")
                                .passwordParameter("password")
                                .defaultSuccessUrl("/", true)
                )
                .logout((logout)-> logout
                        .logoutRequestMatcher(new AntPathRequestMatcher("/members/logout"))
                        .logoutSuccessUrl("/")
                        .invalidateHttpSession(true)
                )

                ;
        return http.build();
    }
    
}

권한설정은 테스트니까 authenticated는 빼두고 진행했다. 로그인, 로그아웃 경로를 설정하고 PasswordEncoder 빈을 등록

비밀번호 저장 로직 수정

private final PasswordEncoder passwordEncoder;

    @Override
    public void join(MemberDTO memberDTO) {
        ...
        Member member = Member.builder()
                .username(memberDTO.getUsername())
                //비밀번호 암호화 완료
                .password(passwordEncoder.encode(memberDTO.getPassword()))
                .nickname(memberDTO.getNickname())
                .email(memberDTO.getEmail())
                .gender(memberDTO.getGender())
                .role(role)
                .build();
		...
    }

passwordEncoder으로 비밀번호 로직 수정

UserDetailsService의 loadUserByUsername 커스텀

@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);
    }

}

loadUserByUsername을 커스텀해서 User 객체로 반환

로그인 폼

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>로그인 폼</title>
</head>
<body>
<h2>Login</h2>
<form action="/members/login" method="post">
    <div>
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" required>
    </div>
    <div>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required>
    </div>
    <div>
        <button type="submit">Login</button>
    </div>
</form>
</body>
</html>

테스트

임시 home 폼

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home</title>
</head>
<body>
<h2></h2>
<a th:href="@{/members/signup}">회원 가입</a>
<a sec:authorize="isAnonymous()" th:href="@{/members/login}" >로그인</a>
<a sec:authorize="isAuthenticated()" th:href="@{/members/logout}" >로그아웃</a>

<a th:href="@{/product/upload}">상품 등록</a>
<a  th:href="@{/product/list}">상품 리스트</a>

</body>
</html>

로그인과 로그아웃을 알아보기위해 isAnonymousisAuthenticated을 사용

임시 home 폼

admin으로 로그인

로그인이 인증되어 로그아웃버튼이 보이는 모습

profile
후회하지 않는 사람이 되자 🔥

0개의 댓글