IT - Development/Spring Boot

[Spring Boot] 스프링 부트 Web Security 설정 방법

happygram 2018. 11. 9. 19:52

Spring Boot 에서는 WebSecurityConfigurerAdapter 를 이용하여 Controller 접근에 대한 통제를 할 수 있습니다.

데이터베이스 (MySQL) 와 연동하여 로그인을 통해 인증을 진행하는 예제를 작성 하겠습니다.

개발 환경은 Spring Boot + Thymeleaf + MySQL 이용을 하였습니다.


전체 흐름

    • 사용자는 login.html 페이지에 접속하여 username 및 password 를 입력한 후 인증을 요청하고, Web Security 를 구현한 클래스에서 데이터베이스로 접근하여, 입력한 정보를 토대로 인증을 합니다.
    • 인증이 완료된 후에는 인증에 대한 정보가 저장되어 있고, 해제될 대까지 세션이 유지됩니다.


ERD

(ERD 추출은 DBeaver (https://dbeaver.io/) 라는 데이터베이스 클라이언트 도구에서 추출 하였습니다)


application.yml

spring:
  profiles:
    active: local # 기본 환경 선택

---
spring: 
  profiles: local
  jpa:
    database: MYSQL
    show-sql: true
    properties:
      hibernate:
        dialect : org.hibernate.dialect.MySQL5InnoDBDialect
        ddl-auto: validate
  datasource:
    url: jdbc:mysql://${HOST}:${PORT}/${NAME}?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
    username: ${USERNAME}
    password: ${PASSWORD}
    platform: mysql
    driver-class-name: com.mysql.jdbc.Driver
    dbcp2:
      validation-query: select 1;


build.gradle

dependencies {
    compile("org.springframework.boot:spring-boot-starter-security")	
}


login.html

<form class="form-signin" method="POST" th:action="@{/login}">
    <h1 class="h3 mb-3 font-weight-normal">[[${login_message}]]</h1>
    <label for="username" class="sr-only">ID</label>
        <input type="text" id="username" name="username" class="form-control" placeholder="ID" required="" autofocus="">
    <label for="password" class="sr-only">Password</label>
        <input type="password" id="password" name="password" class="form-control" placeholder="Password" required="">
    <div class="checkbox mb-3">
        <label><input type="checkbox" value="remember-me"> Remember me</label>
    </div>
    <div align="center" th:if="${param.error}">
        <p style="font-size: 20; color: #FF1C19;">ID or Password invalid, please verify</p>
    </div>
    <button class="btn btn-primary btn-block" type="submit">Sign in</button>
</form>
cs
    • form 에서 action 수행 시 input 태그의 username, password 를 테이블의 컬럼과 비교하여 인증 시 이용하기 때문에 컬럼과 동일하게 주의해서 작성합니다.


WebSecurityConfig.Java

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Autowired
	private DataSource dataSource;
	
    • Spring Boot 설정 파일 application.yml 에서 지정한 spring.datasource 가 dataSource로 자동으로 매핑됩니다.
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/admin", "/admin/*").authenticated()
                .anyRequest().permitAll()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .defaultSuccessUrl("/")
                .and()
            .logout()	
            	.logoutUrl("/logout")
            	.logoutSuccessUrl("/")
            	.invalidateHttpSession(true)
                .permitAll();
    }
    • antMatchers 를 이용하여 Controller 에 매핑할 값을 지정하고 있습니다. 해당 예제에서는 '/admin', '/admin/*' 으로 요청 시 인증을 진행하고, 나머지 모든 경우에는 접근을 허용하고 있습니다.
    • loginPage("/login") 부분은 method=post, action='/login' 요청을 받아서 처리합니다.
    • logoutUrl("/logout") 부분은 method=post, action='logout' 요청을 받아서 처리합니다.
    @Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth
			.jdbcAuthentication()
				.dataSource(dataSource)
				.passwordEncoder(new BCryptPasswordEncoder())
		;
	}
}
    • 위(ERD)에서 언급한 테이블들을 dataSource 로 지정하여 인증 시 이용하고 있습니다. 테이블명 및 컬럼명을 이용하면 인증 항목에 대해서 추가 매핑 하지 않고, 권한과 사용자의 정보를 인증에 사용할 수 있습니다.
    • passwordEncoder는 BCryptPasswordEncoder 를 이용하여 암호화된 데이터에 대해서 복호화를 진행하여 인증합니다.