로그인

Jaewoo Back·2024년 7월 13일
0

Spring Security공부

목록 보기
7/13
post-thumbnail

Spring Security는 HTML Form을 통해 제공되는 사용자 이름 및 암호를 지원합니다.

  1. 사용자는 권한이 부여되지 않은 리소스(/private)에 요청을 합니다.
  2. AuthorizationFilter는 인증되지 않은 요청이 AccessDeniedException을 뱉습니다.
  3. 인증되지 않았으므로 ExceptionTranslationFilter는 AuthenticationEntryPoint를 사용하여 로그인 페이지로 리디렉션을 보냅니다.
  4. 로그인 페이지를 요청합니다.
  5. 로그인 페이지를 렌더링합니다.

form이 제출 되면 UsernamePasswordAuthenticationFiter로 인증합니다.


이 그림은 SecurityFilterChain 다이어그램을 기반으로 합니다.

  1. UsernamePasswordAuthenticationToken 인스턴스에서 사용자 이름과 암호를 추출하여 인증합니다.
  2. 인증에 실패하면
    • SecurityContextHolder가 지워집니다.
    • RememberMeServices.loginFail 가 호출됩니다.
    • AuthenticationFailureHandler 가 호출됩니다.
  3. 인증에 성공하면
    • SessionAuthenticationStrategy 새 로그인에 대한 알림을 받습니다.
    • 인증은 SecurityContextHolder에 설정됩니다.
    • RememberMeServices.loginSuccess 가 호출됩니다.
    • AplicationEventPublisher 를 게시합니다.
    • AuthenticationSuccessHandler 가 호출됩니다. 일반적으로 로그인 페이지로 리디렉션할 때 ExceptionTranslationFilter에 의해 저장된 요청으로 리디렉션

실습

Config 설정 후 로그인 페이지
Spring Security는 Config 클래스 설정 후 특정 경로에 대한 접근 권한이 없는 경우 자동으로 로그인 페이지로 리다이렉팅 되지 않고 오류 페이지가 발생합니다.

이 문제를 해결하기 위해 Config 클래스를 설정하면 로그인 페이지 설정도 진행해야 합니다.


커스텀 로그인 페이지

 login page
    <hr>
    <form action="/loginProc" method="post" name="loginForm">
        <input id="username" type="text" name="username" placeholder="id"/>
        <input id="password" type="password" name="password" placeholder="password"/>
        <input type="submit" value="login"/>
    </form>

/locginProc 경로로 Post 요청


Login Controller

@Controller
public class LoginController {

    @GetMapping("/login")
    public String loginP() {

        return "login";
    }
}

Security Config 로그인 페이지 설정 및 로그인 경로

package com.example.testsecurity.config;

import jakarta.servlet.FilterChain;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {


    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {


        http
                .authorizeHttpRequests(auth -> auth
                .requestMatchers("/", "/login", "/loginProc").permitAll()
                .requestMatchers("/admin").hasRole("ADMIN")
                .requestMatchers("/my/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
        );

        http
                .formLogin((auth) -> auth.loginPage("/login")
                        .loginProcessingUrl("/loginProc")
                        .permitAll()
                );
        
        http
                .csrf(AbstractHttpConfigurer::disable); // 비활성화
        /*csrf는 스프링 시큐리티에서 구현해두었다.  로그인 시 POST 요청 시 CSRF 토큰을 함께 전송해야 하기 때문에 학습과 테스트를 위해 비 활성화*/
        
        return http.build();
    }
}

http://localhost:8080/admin로 페이지 요청시 권한이 없기 때문에 AuthorizationFilter는 인증되지 않은 요청이 AccessDeniedException을 뱉습니다.

인증되지 않았으므로 ExceptionTranslationFilterAuthenticationEntryPoint를 사용하여 로그인 페이지로 리디렉션을 보냅니다.

위에서 만든 login.html로 리디렉션 하고 화면을 렌더링 합니다.

profile
https://blog.naver.com/jaewoo2_25

0개의 댓글