본문 바로가기

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에 저장함으로서, 보안을 설정할 수 있습니다.

  1. @Configuration
  2. @EnableWebSecurity
  3. class SecurityConfig : WebSecurityConfigurerAdapter() {
  4. @Autowired
  5. fun provider() = MyAuthenticationProvider()
  6. override fun configure(auth: AuthenticationManagerBuilder) {
  7. auth.authenticationProvider(provider())
  8. }
  9. override fun configure(web: WebSecurity) {
  10. web.ignoring().antMatchers("/resource/**", "/static/**", "/favicon.ico")
  11. }
  12. override fun configure(http: HttpSecurity) {
  13. http.csrf().disable().httpBasic()
  14. http.headers().frameOptions().disable()
  15. http.authorizeRequests()
  16. .antMatchers("/login").permitAll()
  17. .anyRequest().authenticated()
  18. .and()
  19. .formLogin()
  20. .loginPage("/login").loginProcessingUrl("/auth")
  21. .defaultSuccessUrl("/index", true)
  22. .failureUrl("/login?error")
  23. .and()
  24. .logout()
  25. .logoutSuccessUrl("/login?logout")
  26. .deleteCookies("JSESSIONID")
  27. .invalidateHttpSession(true)
  28. http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true)
  29. }
  30. }
  • 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

  1. <!DOCTYPE html>
  2. <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
  3. <head>
  4. <title>Login page</title>
  5. </head>
  6. <body>
  7. <script type="text/javascript" sec:authorize="isAuthenticated()">
  8. location.href = "/index"
  9. </script>
  10. <h1>Login page</h1>
  11. <div th:if="${param.error}">
  12. 계정과 비밀번호 확인
  13. </div>
  14. <div th:if="${param.logout}">
  15. 로그아웃
  16. </div>
  17. <form th:action="@{/auth}" method="post">
  18. <input type="text" id="username" name="username" autofocus="autofocus" placeholder="id"/> <br />
  19. <input type="password" id="password" name="password" placeholder="pw"/> <br />
  20. <input type="submit" value="Log in" />
  21. </form>
  22. <h3>Admin : admin/123 </h3>
  23. <h3>User : user/456 </h3>
  24. <script src="//code.jquery.com/jquery-2.2.4.min.js"></script>
  25. </body>
  26. </html>
  • 2행 : 타임리프 엔진을 사용한다는 것을 명시합니다 - sec의 경우 1번글에서 보이는 spring security5용을 따로 의존성 추가를 해줘야합니다 (스프링 부트 기본 설정에서 빠짐)
  • 7행 - 9행 : isAutenticated() - 현재 인증이 완료된 상태이면 login페이지가 아닌 index페이지로 연결
  • 12행, 15행 : 각각 get으로 파라미터가 error, logout이 들어오면 아래의 내용을 출력해줍니다
  • 19행 : authentication을 진행할 url ( 위에 configure(httpsecurity)에 지정해준 loginProcessingUrl과 동일해야 합니다)

Index.html

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

 

3. WebMvcConfigurer 구현

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

  1. @Configuration
  2. class MvcConfig : WebMvcConfigurer{
  3. override fun addViewControllers(registry: ViewControllerRegistry) {
  4. registry.addViewController("/login").setViewName("/login")
  5. registry.addViewController("/index").setViewName("/index")
  6. }
  7. }
  • 기본적으로 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