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 를 이용하여 암호화된 데이터에 대해서 복호화를 진행하여 인증합니다.