스프링 시큐리티 커스텀 로그인 폼 만들기

charco·2021년 6월 1일
0

영어해석

목록 보기
2/4

이 글은 스프링 공식 문서를 번역한 글입니다.
번역에 오류가 많을 수 있으니 주의 바랍니다.

출처 : https://docs.spring.io/spring-security/site/docs/4.2.20.RELEASE/guides/html5/form-javaconfig.html


이 가이드는 Hello Spring MVC Security Java Config 의 추가적인 가이드다.

기본 configure(HttpSecurity) 메서드 오버라이딩

우리가 Hello Spring MVC Security Java Config에서 본 것처럼,
스프링 시큐리티의 WebSecurityConfigurerAdapter 클래스는 우리의
애플리케이션을 빠르게 설정하고 구동시킬 수 있도록 해주는 편리한 기본 메서드들을 제공한다. 하지만 우리의 로그인 폼은 애플리케이션의 다른 것들이랑은
달라보인다. 이제 우리만의 커스텀 form을 만들기 위해 configuration을
어떻게 바꿀지 보자.


기본 configure(HttpSecurity)

configure(HttpSecurity)의 기본 설정은 아래와 같다.

protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .anyRequest().authenticated() //1
            .and()
        .formLogin()                      //2
            .and()
        .httpBasic();                     //3
}
  1. 모든 request는 사용자에게 인증을 요구한다.
  2. form 기반의 인증을 지원
  3. HTTP Basic 인증을 지원

커스텀 로그인 페이지 설정

SecurityConfig.java 에 아래와 같이 configure 메서드를 넣는다.

// ...

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login");
    }

    // ...
}

formLogin().permitAll() 메서드는 스프링 시큐리티에게
formLogin()과 관련된 특정 URL(여기서는
/login 과 /login?error)에 모든 사용자의 접근을 허용하도록 지시한다.

formLogin() URL들의 접근 권한 부여는 기본적으로 구현되지 않는다.
왜냐하면 스프링 시큐리티는 어떤게 허용됐고 어떤게 허용되지 않았는지에 대한
가정(assumption)을 만들어야 하기 때문이다.
안전을 위해서라면 자원들의 접근 권한을 확실히 하는게 가장 좋다.

우리의 configuration의 변경을 확인하기 위해 서버를 시작해서 http://localhost:8080/sample/ 에 접근해보자.
이제는 Error resolving template "login" 이라는 500 에러를 받을 것이다.


로그인 페이지 만들기

스프링 MVC 로 우리의 로그인 페이지를 만드는 과정은 두개로 나눌 수 있다.
1.컨트롤러 만들기
2.뷰 만들기

로그인 뷰 컨트롤러 설정

첫번째 단계는 우리의 view 를 가리키는 컨트롤러를 만드는 것이다.
우리의 프로젝트는 javaconfig/messages 프로젝트 의존성을 추가했었다.
이것은 /login 을 위한 뷰 컨트롤러를 이미 포함하고 있기 때문에
따로 컨트롤러를 만들 필요가 없다.
참고를 위해 아래 configuration 이 있다.

// ...

@EnableWebMvc
@ComponentScan("org.springframework.security.samples.mvc")
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

    // ...

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    }
}

로그인 뷰 만들기

우리가 만든 설정에 따르면 우리는 login.html만 만들면 된다.
아래는 그 코드다.

<html xmlns:th="https://www.thymeleaf.org">
  <head th:include="layout :: head(title=~{::title},links=~{})">
    <title>Please Login</title>
  </head>
  <body th:include="layout :: body" th:with="content=~{::content}">
    <div th:fragment="content">
        <form name="f" th:action="@{/login}" method="post">   		  //1               
            <fieldset>
                <legend>Please Login</legend>
                <div th:if="${param.error}" class="alert alert-error">    //2
                    Invalid username and password.
                </div>
                <div th:if="${param.logout}" class="alert alert-success"> //3
                    You have been logged out.
                </div>
                <label for="username">Username</label>
                <input type="text" id="username" name="username"/> 	  //4        
                <label for="password">Password</label>
                <input type="password" id="password" name="password"/>    //5
                <div class="form-actions">
                    <button type="submit" class="btn">Log in</button>
                </div>
            </fieldset>
        </form>
    </div>
  </body>
</html>
  1. 우리가 username과 password를 보낼 URL은 우리의 로그인 폼과 같은 URL이다. 하지만 GET이 아니라 POST로 보낸다는 것을 주의하자.
  2. 인증이 실패하면 브라우저는 /login?error 로 리다이렉트 시킬 것이다.
    error 가 널인지 아닌지에 따라 에러메시지를 보여줄 수 있다.
  3. 성공적으로 로그아웃 되면 브라우저는 /login?logout 으로 리다이렉트 시킬 것이다. error 와 같이 logout이 null이 아니면 화면에 메시지를 보여줄 수 있다.
  4. username
  5. password

인증이 실패한 자세한 이유는 화면에 보여주지 말자. 예를 들어, 우리는
유저가 존재하지 않는다는 것을 화면에 보여주면 안된다. 공격자에게
다른 usename 을 시도해 볼 수 있다는 것을 알려주는 것이다.

우리는 CSRF 토큰을 자동으로 form에 추가하기 위해 Thymeleaf를 사용했다.
만약 Thymeleaf나 Spring MVC의 taglib을 사용하지 않는다면
CSRF 토큰을 직접 추가할 수 있다.

서버를 기작하고 http://localhost:8080/sample/ 에 접속해보자.
로그인 페이지가 보이지만 별로 예쁘진 않을 것이다. 문제는
우리가 css 파일들에 접근 권한 설정을 하지 않았기 때문이다.


정적 자원의 접근 권한 부여

우리는 우리의 자원들과 로그아웃 페이지에 대해 모든 사람들의 접근을 허용하도록
configuration을 수정해야 한다.
아래처럼 수정해라.

// ...

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll() //1 
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()                                    //2
                .permitAll();
    }

    // ...
}
  1. /resources/로 시작하는 URL에 모든 사람의 접근을 허용한다.
    이것은 javascript, css, images 와 같은 정적 자원들의 경로이기 때문에
    그 자원들은 누구나 볼 수 있다.
  2. logout 페이지도 누구나 접근 할 수 있도록 함.

서버를 재시작 해서 http://localhost:8080/sample/ 에 접속해보자.
우리는 이제 애플리케이션의 다른 페이지들과 같이 꾸며진
우리의 커스텀 로그인 페이지를 볼 수 있다.

  • 틀린 username과 password를 입력해보자. 에러 메시지가 뜨는걸 볼 것이다.
  • 맞는 username과 password를 입력해보자. 인증이 성공적으로 될 것이다.
  • 로그아웃 버튼을 눌러보자. 로그아웃 성공 메시지가 보일 것이다.

결론

당신은 이제 스프링 시큐리티의 자바 설정을 통해 커스텀 로그인 폼을
추가 할 수 있을 것이다. 더 많은 것을 배우고 싶다면 아래 링크로 가보자.
Spring Security Guides index page.

profile
아직 배우는 중입니다

0개의 댓글