# Spring Security] springboot + spring security 5.7이후 + tymelefScript

조현수·2023년 7월 10일
1

스프링

목록 보기
3/3

스프링시큐리티의 아주 기본적인 구현부터 단계적으로 진행할것이다.

Spring security 5.7이후의 버전

스프링 시큐리티 버전이 올라가면서 WebSecurityConfigurerAdapter 를 상속받아서 쓰던 방식이

없어지고 메서드체인을 직접 빈을 주입하는 방식으로 바뀌었다.

bulid.gradle

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'

일단 필요한 두가지 기본적인 디펜던시를 추가한다.

login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <title>Login</title>
    <style>
        .container {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }

        .login-box {
            border: 1px solid #ccc;
            padding: 20px;
            border-radius: 5px;
        }
    </style>
</head>
<body>
<div class="container">
    <div class="login-box">
        <h2>Login</h2>
        <div sec:authorize="isAnonymous()">
        <form th:action="@{/api/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>
                <input type="submit" value="Login"/>
            </div>
        </form>
        </div>
    </div>
</div>
</body>
</html>

타임리프로 구현한 html이다.

  1. <html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

    위 선언을 통해 sec변수를 붙이면 springsecurity의 기능들을 편리하게 쓸수 있다. 이 페이지에서는 딱히 사용하는것은 없지만 예를들어.

    이 코드는 모두에게 보여주겠다는 의미이다. 그외에 많은 함수들이 있다.

  2. 스프링시큐리티는 기본적으로 username 과 password라는 변수네이밍을 사용하기때문에 이 네이밍을 그대로 쓰는게 좋다.

  3. 로그인을 누르게 되면 /api/login 으로 데이터가 전송된다.

HomeController

@Controller
public class HomeController {
	@RequestMapping("/")
	public String home() {
		return "hello";
	}

	@RequestMapping("/main")
	public String main() {
		return "main";
	}

	@RequestMapping("/test")
	public String test() {
		return "test";
	}

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

별건없다.

스프링 시큐리티를 위해 전달하는 api들은 스프링콘피그에서 인터셉터할 예정이다.

SecurityConfig

@EnableWebSecurity
/*@AllArgsConstructor*/
@RequiredArgsConstructor
@Configuration
public class SecurityConfig {

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

		http.authorizeRequests(authorize -> {
			try{
				authorize
						.antMatchers("/main")
						.permitAll() // "/main"은 권한 필요없이 접근가능
				.and()
						.formLogin()
						.loginPage("/login") //로그인페이지
						.loginProcessingUrl("/api/login") //이 url을 던지면 spring security에서 인터셉터해온다
						.defaultSuccessUrl("/main",true) //로그인이 성공하면 이 주소로 이동하게 된다.
						;
			}catch (Exception e) {
				throw new RuntimeException(e);
			}
		});

		return http.build();
	}

}

스프링시큐리티 설정들은 이 페이지에서 진행한다.

5.7 이후의 버전임으로 WebSecurityConfigurerAdapter 를 상속받지 않는다.

  1. public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    필터체인을 사용한다,

  2. 타임리프 html에서 보냈던 “/api/login” 은 .loginProcessingUrl("/api/login") 를 통해 스프링시큐리티가 처리할 예정

    이 처리는 service에서 다시 진행한다.

MemberService

@Service
/*@AllArgsConstructor //모든필드의 생성자를 자동으로 추가해준다.*/
public class MemberService implements UserDetailsService {

	@Autowired
	private LoginRepository loginRepository;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

		Member member = loginRepository.findByMemberId(username).orElseThrow(() -> new UsernameNotFoundException("User not found with id : " + username));
		List<GrantedAuthority> authorities = new ArrayList<>();
		authorities.add(new SimpleGrantedAuthority("ADMIN"));

		return new User(member.getEmail(), member.getPw(), authorities);

	}

}

UserDetailsService 를 상속받은 memberService . UserDetailService는 스프링시큐리티 내부 서비스이다. 이 서비스를 상속받으면 시큐리티에서 자동으로 추적이 들어간다.

loadUserByUsername 이 메서드를 오버라이드 해서 할 일은 클라이언트로부터 받은 username정보로 데이터베이스를 조회해 사용자 인증을 수행하는것이다.

말만들으면 복잡하지만 사용자 인증은 스프링시큐리티에서 자동적으로 처리해주니 username으로 디비를 가지고와 User (얘도 스프링시큐리티 내부의 서비스이다.) 에 id 그리고 password 그리고 권한을 담아서 넘기면 된다.

중요한점은 반드시 password를 인코딩해야한다는 점이다.

profile
얼레벌레 꾸준히 하는 사람

0개의 댓글