build.gradle

    implementation 'org.springframework.boot:spring-boot-starter-security'

시큐리티 종속성 추가

SecurityConfig 작성

@Configuration
@EnableWebSecurity
public class SecurityConfig{

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        http.csrf().disable().cors().disable()
                .authorizeHttpRequests()
                    .antMatchers("/", "/auth/login", "/auth/signup").permitAll()
                    .anyRequest().authenticated()
                .and()
                .formLogin()
                    .defaultSuccessUrl("/", true).permitAll()
                    .loginPage("/auth/login")
                    .loginProcessingUrl("/login")
                    .usernameParameter("email")
                .and()
                    .logout()
                    .logoutSuccessUrl("/");

        return http.build();
    }

    /**
     *
     * @return css, js 인증예외처리
     */
    @Bean
    public WebSecurityCustomizer customizer(){
        return web -> web.ignoring().antMatchers("/css/**", "/js/**");
    }

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

SecurityFilterChain

일단 먼저 csrf와 cors는 비활성화해주었다.

"/", "/auth/login", "/auth/signup" 경로는 인증없이 들어갈수있도록하였고
defaultSuccessUrl("/", true) : 로그인 성공시 redirect될 경로
loginPage("/auth/login") : Security에서 제공하는 로그인페이지 대신 커스텀 로그인페이지 사용
loginProcessingUrl("/login") : 로그인 진행 경로인데 로그인시에 /login 경로로 post요청을 보내면된다
usernameParameter("email") : 기본값은 "username"이고 "eamil"로 커스텀하였다
logoutSuccessUrl("/") : logout시에 redirect될 경로이다

WebSecurityCustomizer

bootstrap5를 사용중이기때문에 css파일과 js파일을 static폴더에 따로 저장해놓았다. 그래서 예외처리해주지않으면 적용이되지않기 떄문이다

resources -> static -> css와 js 폴더를 인증에서 예외처리하였다.

PasswordEncoder

비밀번호를 BCryptPasswordEncoder를 이용하여 암호화 처리할것이기떄문에 사용하기 편하게 Bean으로 등록하였다.

MemberServiceImpl 수정

@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;
    private final PasswordEncoder passwordEncoder;


    public void create(MemberDto memberDto){
        memberDto.setPassword(passwordEncoder.encode(memberDto.getPassword()));

        memberRepository.save(memberDto.toEntity());
    }
}

PasswordEncoder를 추가했고 memberDto에서 passwordEncoder를 이용해 암호화한뒤 리포지토리에 저장하도록 하였다.

login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>로그인</title>
    <div th:replace="/fragments/header.html :: header"></div>
</head>
<body>
<div th:replace="/fragments/nav.html :: nav"></div>
<div class="container">
    <h1>로그인</h1>
    <form th:action="@{/login}" method="post">
        <div class="mb-3">
            <label for="email" class="form-label">이메일</label>
            <input type="email" class="form-control" id="email" name="email" required>
        </div>
        <div class="mb-3">
            <label for="password" class="form-label">비밀번호</label>
            <input type="password" class="form-control" id="password" name="password" required>
        </div>
        <button type="submit" class="btn btn-primary">로그인</button>
    </form>
</div>
</body>
</html>

이메일과 비밀번호를 입력받아 /login 경로로 post요청

AuthController 추가

@Controller
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {

    private final MemberService memberService;

    @GetMapping("/login")
    public String login(){
        return "auth/login";
    }

                ...
}

/auth/login 경로로 get요청시 login 페이지 표시하도록 추가하였다.

Junyoung.dev