Search

๋กœ๊ทธ์ธ

๋กœ๊ทธ์ธ

Spring Security 6

์ด์ „ ํŽ˜์ด์ง€

์ด์ „ ํŽ˜์ด์ง€ ๋‚ด์šฉ์— ์ด์–ด์„œ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

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 - ์ธ์ฆ ๊ด€๋ฆฌ์ž ๋นˆ ๋“ฑ๋ก
( PasswordEncoder ๋นˆ ๋“ฑ๋ก์€ ํšŒ์› ๊ฐ€์ž… ์—์„œ ๋“ฑ๋กํ•จ )

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)

๋‹ค์Œ ์ฃผ์ œ