본문 바로가기

SW개발

Kotlin + Spring boot security + thymeleaf 로그인 구현(3)

2019/03/28 - [SW개발] - Kotlin + Spring boot security + thymeleaf 로그인 구현(1)

2019/04/01 - [SW개발] - Kotlin + Spring boot security + thymeleaf 로그인 구현(2)

이전 글까지, 따라왔다면 여기까지 만들어졌을겁니다.

이번 글에서는 Spring Security를 통해, 이전 글에서 만든 Provider를 빈으로 등록하고, 이를 통해 인증을 처리하는 config를 구현하겠습니다


1. WebSeurityConfigurerAdpater 구현

이 인터페이스는, 스프링 시큐리티에서 가장 핵심 적인 역할을 합니다.

  • AuthenticationManagerBuilder :  AuthenticationProvider 설정
  • WebSecurity : 전역 보안에 영향을 주는 구성 설정
  • HttpSecurity : 어떠한 URL 경로를 보호해야하는지에 대한 정의, 자신만의 인증 매커니즘 정의

위의 세가지를, configure에 저장함으로서, 보안을 설정할 수 있습니다.

@Configuration
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {

    @Autowired
    fun provider() = MyAuthenticationProvider()


    override fun configure(auth: AuthenticationManagerBuilder) {
        auth.authenticationProvider(provider())
    }

    override fun configure(web: WebSecurity) {
        web.ignoring().antMatchers("/resource/**", "/static/**", "/favicon.ico")
    }

    override fun configure(http: HttpSecurity) {
        http.csrf().disable().httpBasic()
        http.headers().frameOptions().disable()

        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login").loginProcessingUrl("/auth")
                .defaultSuccessUrl("/index", true)
                .failureUrl("/login?error")
                .and()
                .logout()
                .logoutSuccessUrl("/login?logout")
                .deleteCookies("JSESSIONID")
                .invalidateHttpSession(true)

        http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true)
    }


}
  • 1행 : @Cofiguration 어노테이션을 통해, configuration으로 등록합니다
  • 2행 : WebSecurityConfigurerAdapter와 함께 사용되며, 스프링 시큐리티를 사용할 때 사용합니다
  • 6행 : 이전에 만든 AuthenticationProvider를 빈으로 등록해줍니다
  • 10행 : AuthenticationManageBuilder를 provider를 통해, 실질적 인증절차를 진행하게 해줍니다
  • 14행 : 해당 접근에 대해, 무시를 해주는 코드를 넣습니다(전역)
  • 18행 : csrf를 꺼줍니다 (Csrf를 사용할 때에는 필요 없는 코드입니다)
  • 21행 : authorize에 관한 동작입니다
  • 22행, 23행 : "/login"은 전체에게 공개, 이외에는 authentication을 통해 권한을 얻은 사람만 접근하게 합니다
  • 25행 - 28행 : login에 관한 내용입니다
  • 30행 - 33행 : logout에 관한 내용입니다
  • 35행 : 세션 관리입니다. 현재 맥시멈을 1개로 두어, 동시로그인이 불가능하게 했습니다 

 

2. login page, index page 구현

Spring security는 기본 로그인 페이지를 지원하지만, 보통은 커스텀 로그인 페이지를 만들고자 할 것입니다. 저는 타임리프 템플릿 엔진을 통해 로그인페이지를 간단히 구현하겠습니다. 

  • 타임리프는 기본적으로 resource 밑에, templates에 html파일을 통해 구현할 수 있습니다
  • 로그인 페이지인 login.html과 , 로그인에 성공했을 때 들어가는 index.html을 만들었습니다

login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"  xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <title>Login page</title>
</head>
<body>
    <script type="text/javascript" sec:authorize="isAuthenticated()">
        location.href = "/index"
    </script>

    <h1>Login page</h1>
    <div th:if="${param.error}">
        계정과 비밀번호 확인
    </div>
    <div th:if="${param.logout}">
        로그아웃
    </div>

    <form th:action="@{/auth}" method="post">
        <input type="text" id="username" name="username" autofocus="autofocus" placeholder="id"/> <br />
        <input type="password" id="password" name="password" placeholder="pw"/> <br />
        <input type="submit" value="Log in" />
    </form>


    <h3>Admin : admin/123 </h3>
    <h3>User : user/456 </h3>
    <script src="//code.jquery.com/jquery-2.2.4.min.js"></script>
</body>
</html>
  • 2행 : 타임리프 엔진을 사용한다는 것을 명시합니다 - sec의 경우 1번글에서 보이는 spring security5용을 따로 의존성 추가를 해줘야합니다 (스프링 부트 기본 설정에서 빠짐)
  • 7행 - 9행 : isAutenticated() - 현재 인증이 완료된 상태이면 login페이지가 아닌 index페이지로 연결
  • 12행, 15행 : 각각 get으로 파라미터가 error, logout이 들어오면 아래의 내용을 출력해줍니다
  • 19행 : authentication을 진행할 url ( 위에 configure(httpsecurity)에 지정해준 loginProcessingUrl과 동일해야 합니다)

Index.html

<!DOCTYPE html>
<html xmlns:sec="http://www.thymeleaf.org/extras/spring-security" >
<head>
    <meta charset="UTF-8">
    <title>Example</title>
</head>
<body>
    <span sec:authorize="hasRole('ROLE_ADMIN')">
        <button>
            <a href="/logout"><h2>ADMIN Logout</h2></a>
        </button>
    </span>
    <span sec:authorize="hasRole('ROLE_USER')">
        <button>
            <a href="/logout"><h2>USER Logout</h2></a>
        </button>
    </span>
</body>
</html>
  • 8행, 13행 : sec:auhtorize="hasRole('~~')" : ~~라는 권한을 가질 경우, 동작하게 하는 함수입니다
  • 10행, 14행 : "/logout" - httpsecurity에 정해놓은, logout url로 가게 해줍니다

 

3. WebMvcConfigurer 구현

index페이지와, login페이지를 연결해줄 Configuerer를 구현합니다

@Configuration
class MvcConfig : WebMvcConfigurer{
    override fun addViewControllers(registry: ViewControllerRegistry) {
        registry.addViewController("/login").setViewName("/login")
        registry.addViewController("/index").setViewName("/index")
    }
}
  • 기본적으로 resource/templates 가 기본으로 설정돼 있습니다
  • 3행 : ViewControllerRegistry에 /login url(controller)에, login.html(view)를 등록해줍니다 
  • 4행 : 3행과 마찬가지로 index를 등록합니다



  • 여기까지 따라오셨다면 기본적인 로그인 구현은 끝이났습니다.

4. 실행 결과

  • 스프링 부트를 실행 시켜준 뒤, localhost:8080(기본호스트)로 연결해준 화면입니다

  • admin, 123으로 Login했을 때의 화면입니다. role이 ROLE_ADMIN이기 때문에, ADMIN_Logout버튼이 나옵니다.
  • Logout을 누르면 다시 loginpage로 돌아갑니다

  • 로그아웃을 했기 때문에, logout파라미터가 붙었기 때문에, 로그아웃을 출력해줬습니다

  • user로 로그인을 했을 때의 페이지입니다. 

지금까지 Spring Security를 이용하여, 간단한 로그인 페이지를 구현해보았습니다.

궁금한 점이 있다면 댓글 달아주세요


https://github.com/bobfull/spring-kotlin-security-study

  • 예제 코드가 있는 github 주소입니다.
 

bobfull/spring-kotlin-security-study

Contribute to bobfull/spring-kotlin-security-study development by creating an account on GitHub.

github.com