๋ก๊ทธ์ธ
์ด์ ํ์ด์ง
์ด์ ํ์ด์ง ๋ด์ฉ์ ์ด์ด์ ์งํํฉ๋๋ค.
Code
Preview
1.
๋ฉ์ธ ํ๋ฉด
2.
๋ก๊ทธ์ธ ํ๋ฉด
์์ ํ๋ก์ธ์ค
1.
ํ๋ก์ ํธ ์์ฑ
2.
์คํ๋ง ์ํ๋ฆฌํฐ ์ค์
3.
์์ฒญ ๊ฒฝ๋ก ๋งคํ
Preview
1.
๋ฉ์ธ ํ๋ฉด
2.
๋ก๊ทธ์ธ ํ๋ฉด
3.
๋ฉ์ธ ํ๋ฉด (๋ก๊ทธ์ธ ์๋ฃ)
๋ฉ์ธ ํ๋ฉด
๋ก๊ทธ์ธ ํ๋ฉด
๋ฉ์ธ ํ๋ฉด (๋ก๊ทธ์ธ ์๋ฃ)
์์ ํ๋ก์ธ์ค
1.
ํ๋ก์ ํธ ์์ฑ
โข
build.gradle
โข
spring boot version : 3.x.x
โข
spring security version : 6.x.x
โข
์์กด์ฑ ์ค์
โฆ
Spring Web
โฆ
Spring Boot DevTools
โฆ
Spring Security
โฆ
Lombok
โฆ
Thymeleaf
โฆ
MySQL Driver
โฆ
Mybatis Framework
2.
์คํ๋ง ์ํ๋ฆฌํฐ ์ค์
โข
~/config/SecurityConfig.java
ํ๋ก์ ํธ ์์ฑ
build.gradle
spring boot 3.x.x
spring security 6.x.x
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.3.5'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.aloha'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
Java
๋ณต์ฌ
์คํ๋ง ์ํ๋ฆฌํฐ ์ค์
~/config/SecurityConfig.java
UserDetailsService - JDBC ์ธ์ฆ๋ฐฉ์ ๋น ๋ฑ๋ก
AuthenticationManager - ์ธ์ฆ ๊ด๋ฆฌ์ ๋น ๋ฑ๋ก
UserDetailsService ๋น ๋ฑ๋ก
UserDetailsService ๋น์ ๋ฑ๋กํ์ฌ, ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๋ SQL ์ฟผ๋ฆฌ๋ฅผ ์ค์ ํด์ฃผ์ด ์ธ์ฆ ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํ๋ค.
โข
์ฌ์ฉ์ ์ธ์ฆ ์ฟผ๋ฆฌ
โข
์ฌ์ฉ์ ๊ถํ ์ฟผ๋ฆฌ
@Bean
public UserDetailsService userDetailsService() {
JdbcUserDetailsManager userDetailsManager
= new JdbcUserDetailsManager(dataSource);
// ์ฌ์ฉ์ ์ธ์ฆ ์ฟผ๋ฆฌ
String sql1 = " SELECT username, password, enabled "
+ " FROM user "
+ " WHERE username = ? "
;
// ์ฌ์ฉ์ ๊ถํ ์ฟผ๋ฆฌ
String sql2 = " SELECT username, auth "
+ " FROM user_auth "
+ " WHERE username = ? "
;
userDetailsManager.setUsersByUsernameQuery(sql1);
userDetailsManager.setAuthoritiesByUsernameQuery(sql2);
return userDetailsManager;
}
Java
๋ณต์ฌ
AuthenticationManager ๋น ๋ฑ๋ก
/**
* ๐ AuthenticationManager ์ธ์ฆ ๊ด๋ฆฌ์ ๋น ๋ฑ๋ก
* @param authenticationConfiguration
* @return
* @throws Exception
*/
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration ) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
Java
๋ณต์ฌ
SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private DataSource dataSource;
// ์คํ๋ง ์ํ๋ฆฌํฐ ์ค์ ๋ฉ์๋
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// โ
์ธ๊ฐ ์ค์
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/**").permitAll());
// ๐ ํผ ๋ก๊ทธ์ธ ์ค์
http.formLogin( login -> login.permitAll() );
return http.build();
}
/**
* ๐ ๋น๋ฐ๋ฒํธ ์ํธํ ๋น ๋ฑ๋ก
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* ๐ AuthenticationManager ์ธ์ฆ ๊ด๋ฆฌ์ ๋น ๋ฑ๋ก
* @param authenticationConfiguration
* @return
* @throws Exception
*/
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration ) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
/**
* ๐ฎโโ๏ธ๐ ์ฌ์ฉ์ ์ธ์ฆ ๊ด๋ฆฌ ๋น ๋ฑ๋ก ๋ฉ์๋
* JDBC ์ธ์ฆ ๋ฐฉ์
* โ
๋ฐ์ดํฐ ์์ค (URL, ID, PW) - application.properties
* โ
SQL ์ฟผ๋ฆฌ ๋ฑ๋ก
* โญ ์ฌ์ฉ์ ์ธ์ฆ ์ฟผ๋ฆฌ
* โญ ์ฌ์ฉ์ ๊ถํ ์ฟผ๋ฆฌ
* @return
*/
@Bean
public UserDetailsService userDetailsService() {
JdbcUserDetailsManager userDetailsManager
= new JdbcUserDetailsManager(dataSource);
// ์ฌ์ฉ์ ์ธ์ฆ ์ฟผ๋ฆฌ
String sql1 = " SELECT username, password, enabled "
+ " FROM user "
+ " WHERE username = ? "
;
// ์ฌ์ฉ์ ๊ถํ ์ฟผ๋ฆฌ
String sql2 = " SELECT username, auth "
+ " FROM user_auth "
+ " WHERE username = ? "
;
userDetailsManager.setUsersByUsernameQuery(sql1);
userDetailsManager.setAuthoritiesByUsernameQuery(sql2);
return userDetailsManager;
}
}
Java
๋ณต์ฌ
HomeController.java
@GetMapping("")
public String home(@AuthenticationPrincipal User authAuth, Model model) throws Exception {
log.info(":::::::::: ๋ฉ์ธ ํ๋ฉด ::::::::::");
String username = authAuth.getUsername(); // ์ธ์ฆ๋ ์ฌ์ฉ์ ์์ด๋
log.info("username : " + username);
Users user = userService.select(username); // ์์ด๋๋ก ํ์ ์ ๋ณด ์กฐํ
log.info("user : " + user);
model.addAttribute("user", user); // ๋ชจ๋ธ์ ์ฌ์ฉ์ ๊ฐ์ฒด ๋ฑ๋ก
return "index";
}
Java
๋ณต์ฌ
๋ฉ์ธ ํ๋ฉด์์ ์ธ์ฆ๋ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์์ ์ถ๋ ฅํด๋ณด๊ฒ ์ต๋๋ค.
@AuthenticationPrincipal
ํ์ฌ ์ธ์ฆ๋ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ์ฃผ์
๋ฐ์ต๋๋ค.
org.springframework.security.core.userdetails.User ๊ฐ์ฒด ์ ๋ณด๋ก ์ธ์ฆ๋ ์ฌ์ฉ์ ์ ๋ณด์ ๊ฐ์ ธ์จ๋ค.
๋ฉ์๋ | ์ค๋ช
|
getUsername() | ์ธ์ฆ๋ ์ฌ์ฉ์์ ์ฌ์ฉ์๋ช
(username) ์์ด๋๋ฅผ ๋ฐํํฉ๋๋ค. |
getPassword() | ์ธ์ฆ๋ ์ฌ์ฉ์์ ์ํธ (password)๋ฅผ ๋ฐํํฉ๋๋ค. |
getAuthorities() | ์ฌ์ฉ์์ ๊ถํ ๋ชฉ๋ก์ ๋ฐํํฉ๋๋ค. GrantedAuthority ๊ฐ์ฒด์ ๋ฆฌ์คํธ๋ฅผ ๋ฐํํฉ๋๋ค. |
isEnabled() | ์ฌ์ฉ์๊ฐ ํ์ฑํ ๋์ด ์๋์ง ์ฌ๋ถ๋ฅผ ๋ฐํํฉ๋๋ค. (ํ์ฑํ๋๋ฉด true, ๋นํ์ฑํ๋๋ฉด false) |
isAccountNonExpired() | ์ฌ์ฉ์์ ๊ณ์ ์ด ๋ง๋ฃ๋์ง ์์๋์ง ์ฌ๋ถ๋ฅผ ๋ฐํํฉ๋๋ค. (๊ณ์ ์ด ๋ง๋ฃ๋์ง ์์ผ๋ฉด true) |
isCredentialsNonExpired() | ์ฌ์ฉ์์ ์๊ฒฉ ์ฆ๋ช
(๋น๋ฐ๋ฒํธ ๋ฑ)์ด ๋ง๋ฃ๋์ง ์์๋์ง ์ฌ๋ถ๋ฅผ ๋ฐํํฉ๋๋ค. (๋น๋ฐ๋ฒํธ๊ฐ ๋ง๋ฃ๋์ง ์์ผ๋ฉด true) |
isAccountNonLocked() | ์ฌ์ฉ์์ ๊ณ์ ์ด ์ ๊ฒจ ์์ง ์์์ง ์ฌ๋ถ๋ฅผ ๋ฐํํฉ๋๋ค. (์ ๊ธฐ์ง ์์ผ๋ฉด true) |