본문 바로가기
Spring/구현

[Spring Security] 폼 POST 로그인 로그아웃 구현하기

by 롱싱싱 2024. 10. 23.

Spring Security에서 로그인과 로그아웃 폼을 구현할 때,

보안을 강화하기 위해 CSRF(Cross-Site Request Forgery) 토큰이 필요하다.

이 토큰은 서버에서 생성되어 클라이언트에 전달되며,

이후 클라이언트가 서버에 요청을 보낼 때 함께 전송된다.

이를 통해 악의적인 제3자가 사용자 모르게 요청을 조작하는 것을 방지할 수 있다.

 

form 로그인 html

<form th:action="@{/login}"  method="POST" >
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    <div class="form-group">
        <label for="username">아이디:</label>
        <input type="text" class="form-control" id="username" name="username" required>
    </div>
    <div class="form-group">
        <label for="password">비밀번호:</label>
        <input type="password" class="form-control" id="password" name="password" required>
    </div>
    <div class="form-group">
        <label>
            <input type="checkbox" name="remember" id="remember"> 로그인 상태 유지
        </label>
    </div>
    <button type="submit" class="btn btn-primary">로그인</button>
    <a href="javascript:history.back();" class="btn btn-default">취소</a>
</form>

 

  • th:action="@{/login}"은 Spring Security에서 제공하는 로그인 URL로 데이터를 전송하기 위한 속성이다.
  • CSRF 토큰은 <input type="hidden">으로 추가되며, 이를 통해 서버가 CSRF 공격을 방지할 수 있게 된다.
  • 로그인 폼에서 사용자는 username과 password 필드를 입력한 후, 서버로 데이터를 전송하여 인증을 요청한다.
  • '로그인 상태 유지' 체크박스는 사용자가 세션을 유지할지 여부를 선택할 수 있게 한다.

 

 

form 로그아웃

@PostMapping(value = "/logout")
public String logout(HttpServletRequest request, HttpServletResponse response) {
    Authentication authentication = SecurityContextHolder.getContextHolderStrategy().getContext().getAuthentication();
    if (authentication != null) {
        new SecurityContextLogoutHandler().logout(request, response, authentication);
    }
    return "redirect:/";

}
<form th:action="@{/logout}"  method="POST" >
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    <input type="submit" id="logoutButton" value="로그아웃"></input>
</form>

 

여러 블로그를 돌아다녀 봤는데 logout을 주로 GET으로 처리하는 코드가 많았다. login할 때와 마찬가지로 폼에 csrf토큰을 추가했고 controllerd에 logout을 postMapping하니 정상적으로 잘 동작했다.

  • th:action="@{/logout}"는 로그아웃 요청을 처리하는 Spring Security의 URL.
  • 마찬가지로 CSRF 토큰을 사용하여 로그아웃 요청 시에도 보안이 유지된다.
  • 폼을 제출하면 사용자는 세션이 종료되고 로그아웃 처리가 완료된다.

 

공부를 더 하고 나서 로그인 방식을 Ajax로 바꿔볼 예정이다.

Ajax로 바꾸면 클라이언트에서 서버로 요청을 보내는 동안 페이지가 새로 고쳐지지 않고, 다른 작업을 수행할 수 있다.

 

CSRF 토큰의 필요성

Spring Security에서는 POST 방식으로 서버에 요청을 보낼 때, CSRF 토큰이 필수다. CSRF 토큰은 사용자에게 발급된 세션과 연동되어 있으며, 요청이 유효한 사용자로부터 왔는지를 확인하는 역할을 한다. 폼에 <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">와 같은 CSRF 토큰 필드를 추가함으로써 CSRF 공격을 예방할 수 있다.

 

SecurityFilterChain

http
        .authorizeHttpRequests(auth -> auth
                .requestMatchers("/").permitAll()
                .anyRequest().authenticated())
        .formLogin(login -> login
                .loginPage("/login")
                .loginProcessingUrl("/login")
                .defaultSuccessUrl("/", false)
                .successHandler(((request, response, authentication) -> {
                    response.sendRedirect("/");
                }))
                .usernameParameter("username")
                .passwordParameter("password")
                .permitAll()
        )
        .anonymous(anonymous -> anonymous
                        .principal("guest")
                        .authorities("ROLE_GUEST")
         )
        .logout(logout -> logout
               .logoutUrl("/logout")
               .logoutSuccessUrl("/")
               .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "POST"))
               .logoutSuccessHandler(((request, response, authentication) -> {
                        response.sendRedirect("/");
                }))
        )

 

'Spring > 구현' 카테고리의 다른 글

[Spring Security] RememberMe 구현  (0) 2024.10.23