pom.xml
에서 의존성 추가.<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
<scope>runtime</scope>
</dependency>
spring:
h2:
console:
enabled: true
path: /h2-console
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/assets/**", "/h2-console/**");
}
pom.xml
에서 추가해준다.<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
spring boot starter jdbc
추가.<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.lazyluke</groupId>
<artifactId>log4jdbc-remix</artifactId>
<version>0.2.7</version>
</dependency>
spring:
datasource:
driver-class-name: org.h2.Driver
url: "jdbc:h2:mem:spring_security;MODE=MYSQL;DB_CLOSE_DELAY=-1"
username: sa
password:
hikari:
minimum-idle: 1
maximum-pool-size: 5
pool-name: H2_DB
spring_security
데이터 베이스 이름MODE=MYSQL
MySQL모드DB_CLOSE_DELAY
어플리케이션이 종료될때까지 h2를 클로즈하지 않음.h2:mem
h2데이터베이스를 인메모리 데이터베이스로 사용하겠다는 의미.spring:
sql:
init:
platform: h2
schema-locations: classpath:sql/schema.sql
data-locations: classpath:sql/data.sql
encoding: UTF-8
@Component
public class DataSourcePostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof DataSource && !(bean instanceof Log4jdbcProxyDataSource)) {
return new Log4jdbcProxyDataSource((DataSource) bean);
} else {
return bean;
}
}
}
DataSource 객체를 Log4jdbcProxyDataSource 타입으로 Wrapping 처리하기 위한 BeanPostProcessor
<logger name="jdbc.sqltiming" level="INFO"/>
<logger name="jdbc.audit" level="OFF"/>
<logger name="jdbc.resultset" level="OFF"/>
<logger name="jdbc.resultsettable" level="INFO"/>
<logger name="jdbc.connection" level="OFF"/>
<logger name="jdbc.sqlonly" level="OFF"/>
logback.xml — log4jdbc 선택적 로깅 설정
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
select username, password, enabled from users where username = ? -- 사용자 조회
select username, authority from authorities where username = ? -- 사용자의 권한 조회
JdbcDaoImpl 클래스에서 사용자 및 권한 조회를 위해 사용되는 기본 Query
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource);
}
inMemoryAuthentication 메소드는 UserDetailsService 인터페이스 구현체로 InMemoryUserDetailsManager 객체를 등록했었다.
👍 sql 디렉토리 아래에 schema_new.sql, data_new.sql 쿼리 파일은 Group-based Access Control 기능을 사용할 있도록 데이터베이스에 테이블을 생성하고, 필요한 데이터를 입력한다.
👍 sql 디렉토리 아래에 data_new.sql 쿼리 파일에는 두 개의 사용자 계정 (user, admin) 더미 데이터가 정의되어 있는데, 비밀번호가 BCrypt Hash로 암호화되어 있다. 암호화 되기 이전 비밀번호는 user123, admin123 이다.
select username, password, enabled from users where username = ?
select username, authority from authorities where username = ?
select g.id, g.group_name, ga.authority
from groups g, group_members gm, group_authorities ga
where gm.username = ? and g.id = ga.group_id and g.id = gm.group_id
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(
"SELECT " +
"login_id, passwd, true " +
"FROM " +
"USERS " +
"WHERE " +
"login_id = ?"
)
.groupAuthoritiesByUsername(
"SELECT " +
"u.login_id, g.name, p.name " +
"FROM " +
"users u JOIN groups g ON u.group_id = g.id " +
"LEFT JOIN group_permission gp ON g.id = gp.group_id " +
"JOIN permissions p ON p.id = gp.permission_id " +
"WHERE " +
"u.login_id = ?"
)
.getUserDetailsService().setEnableAuthorities(false)
;
}