Search

๋ฐ”๋กœ ๋กœ๊ทธ์ธ

๋ฐ”๋กœ ๋กœ๊ทธ์ธ

Spring Security 6

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

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

Code

Preview

1.
ํšŒ์› ๊ฐ€์ž… ํ™”๋ฉด
2.
๋ฉ”์ธ ํ™”๋ฉด

์ž‘์—… ํ”„๋กœ์„ธ์Šค

1.
ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ
2.
ํ”„๋กœ์ ํŠธ ์„ค์ •
3.
์„œ๋น„์Šค
4.
์ปจํŠธ๋กค๋Ÿฌ

Preview

1.
ํšŒ์› ๊ฐ€์ž… ํ™”๋ฉด
2.
๋ฉ”์ธ ํ™”๋ฉด

ํšŒ์› ๊ฐ€์ž… ํ™”๋ฉด

ํšŒ์› ๊ฐ€์ž… ์ฒ˜๋ฆฌ ๋ฐ”๋กœ ๋กœ๊ทธ์ธ ๋ฉ”์ธ ํ™”๋ฉด
ํšŒ์› ๊ฐ€์ž… ์š”์ฒญ ์‹œ, ํšŒ์› ๊ฐ€์ž…์ด ์„ฑ๊ณตํ•˜๊ฒŒ ๋˜๋ฉด ๋ฐ”๋กœ ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ ํ›„ ๋ฉ”์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

๋ฉ”์ธ ํ™”๋ฉด

์ž‘์—… ํ”„๋กœ์„ธ์Šค

1.
ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ
2.
ํ”„๋กœ์ ํŠธ ์„ค์ •
3.
์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •
4.
์„œ๋น„์Šค
5.
์ปจํŠธ๋กค๋Ÿฌ

ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

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
๋ณต์‚ฌ

ํ”„๋กœ์ ํŠธ ์„ค์ •

application.properties

spring.application.name=form-jointologin # ๋ฐ์ดํ„ฐ ์†Œ์Šค - MySQL spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/aloha?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true spring.datasource.username=aloha spring.datasource.password=123456 # Mybatis ์„ค์ • mybatis.configuration.map-underscore-to-camel-case=true mybatis.type-aliases-package=com.aloha.security6.domain mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Markdown
๋ณต์‚ฌ

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •

SecurityConfig.java

package com.aloha.security6.config; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.JdbcUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; import lombok.extern.slf4j.Slf4j; @Slf4j @Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private DataSource dataSource; // ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ • ๋ฉ”์†Œ๋“œ @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // โœ… ์ธ๊ฐ€ ์„ค์ • http.authorizeHttpRequests(auth -> auth .requestMatchers("/**").permitAll() .anyRequest().permitAll() ); // ๐Ÿ” ํผ ๋กœ๊ทธ์ธ ์„ค์ • http.formLogin( login -> login.permitAll() ); // ๐Ÿ”„ ์ž๋™ ๋กœ๊ทธ์ธ ์„ค์ • http.rememberMe(me -> me.key("aloha") .tokenRepository(tokenRepository()) .tokenValiditySeconds(60 * 60 * 24 * 7)); // 7์ผ ์œ ํšจ์‹œ๊ฐ„ (์ดˆ๋‹จ์œ„) 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 ์ธ์ฆ ๋ฐฉ์‹ ๋นˆ ๋“ฑ๋ก * @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; } /** * ๐Ÿƒ ์ž๋™ ๋กœ๊ทธ์ธ ์ €์žฅ์†Œ ๋นˆ ๋“ฑ๋ก * โœ… ๋ฐ์ดํ„ฐ ์†Œ์Šค * โญ persistent_logins ํ…Œ์ด๋ธ” ์ƒ์„ฑ create table persistent_logins ( username varchar(64) not null , series varchar(64) primary key , token varchar(64) not null , last_used timestamp not null ); * ๐Ÿ”„ ์ž๋™ ๋กœ๊ทธ์ธ ํ”„๋กœ์„ธ์Šค * โœ… ๋กœ๊ทธ์ธ ์‹œ * โžก ๐Ÿ‘ฉโ€๐Ÿ’ผ(ID, ์‹œ๋ฆฌ์ฆˆ, ํ† ํฐ) ์ €์žฅ * โœ… ๋กœ๊ทธ์•„์›ƒ ์‹œ, * โžก ๐Ÿ‘ฉโ€๐Ÿ’ผ(ID, ์‹œ๋ฆฌ์ฆˆ, ํ† ํฐ) ์‚ญ์ œ * @return */ @Bean public PersistentTokenRepository tokenRepository() { // JdbcTokenRepositoryImpl : ํ† ํฐ ์ €์žฅ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ฐ์ฒด JdbcTokenRepositoryImpl repositoryImpl = new JdbcTokenRepositoryImpl(); // โœ… ํ† ํฐ ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ ์†Œ์Šค ์ง€์ • // - ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ์ž๋™ ๋กœ๊ทธ์ธ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ DB๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. repositoryImpl.setDataSource(dataSource); // ์„œ๋ฒ„ ์‹คํ–‰ ์‹œ, ์ž๋™ ๋กœ๊ทธ์ธ ํ…Œ์ด๋ธ” ์ž๋™ ์ƒ์„ฑ // repositoryImpl.setCreateTableOnStartup(true); // persistent_logins ํ…Œ์ด๋ธ” ์ƒ์„ฑ try { repositoryImpl.getJdbcTemplate().execute(JdbcTokenRepositoryImpl.CREATE_TABLE_SQL); } catch (BadSqlGrammarException e) { log.error("persistent_logins ํ…Œ์ด๋ธ”์ด ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."); } catch (Exception e) { log.error("์ž๋™ ๋กœ๊ทธ์ธ ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์ค‘ , ์˜ˆ์™ธ ๋ฐœ์ƒ"); } return repositoryImpl; } }
Java
๋ณต์‚ฌ

์„œ๋น„์Šค

โ€ข
UserService.java
โ€ข
UserServiceImpl.java

UserService.java

login() ๋ฉ”์†Œ๋“œ๋ฅผ ์ถ”๊ฐ€๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
public interface UserService { // ๋กœ๊ทธ์ธ public boolean login(Users user) throws Exception; // ์กฐํšŒ public Users select(String username) throws Exception; // ํšŒ์› ๊ฐ€์ž… public int join(Users user) throws Exception; // ํšŒ์› ์ˆ˜์ • public int update(Users user) throws Exception; // ํšŒ์› ๊ถŒํ•œ ๋“ฑ๋ก public int insertAuth(UserAuth userAuth) throws Exception; }
Java
๋ณต์‚ฌ

UserServiceImpl.java

ํšŒ์› ๊ฐ€์ž… ์‹œ, ์ž…๋ ฅํ•œ ๋กœ๊ทธ์ธ ์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ์ธ ์ธ์ฆ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜๋„๋ก ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Autowired private PasswordEncoder passwordEncoder; @Autowired private AuthenticationManager authenticationManager; @Override public boolean login(Users user, HttpServletRequest request) throws Exception { // ๐Ÿ’ ํ† ํฐ ์ƒ์„ฑ String username = user.getUsername(); // ์•„์ด๋”” String password = user.getPassword(); // ์•”ํ˜ธํ™”๋˜์ง€ ์•Š์€ ๋น„๋ฐ€๋ฒˆํ˜ธ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); // ํ† ํฐ์„ ์ด์šฉํ•˜์—ฌ ์ธ์ฆ Authentication authentication = authenticationManager.authenticate(token); // ์ธ์ฆ ์—ฌ๋ถ€ ํ™•์ธ boolean result = authentication.isAuthenticated(); // ์ธ์ฆ์ด ์„ฑ๊ณตํ•˜๋ฉด SecurityContext์— ์„ค์ • if (result) { SecurityContextHolder.getContext().setAuthentication(authentication); // ์„ธ์…˜์— ์ธ์ฆ ์ •๋ณด ์„ค์ • (์„ธ์…˜์ด ์—†์œผ๋ฉด ์ƒˆ๋กœ ์ƒ์„ฑ) HttpSession session = request.getSession(true); // ์„ธ์…˜์ด ์—†์œผ๋ฉด ์ƒˆ๋กœ ์ƒ์„ฑ session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext()); } return result; } @Override public Users select(String username) throws Exception { Users user = userMapper.select(username); return user; } @Override public int join(Users user) throws Exception { String username = user.getUsername(); String password = user.getPassword(); String encodedPassword = passwordEncoder.encode(password); // ๐Ÿ”’ ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™” user.setPassword(encodedPassword); // ํšŒ์› ๋“ฑ๋ก int result = userMapper.join(user); if( result > 0 ) { // ํšŒ์› ๊ธฐ๋ณธ ๊ถŒํ•œ ๋“ฑ๋ก UserAuth userAuth = new UserAuth(); userAuth.setUsername(username); userAuth.setAuth("ROLE_USER"); result = userMapper.insertAuth(userAuth); } return result; } @Override public int update(Users user) throws Exception { int result = userMapper.update(user); return result; } @Override public int insertAuth(UserAuth userAuth) throws Exception { int result = userMapper.insertAuth(userAuth); return result; } }
Java
๋ณต์‚ฌ

์ปจํŠธ๋กค๋Ÿฌ

- ~/controller/HomeController.java

~/controller/HomeController.java

ํšŒ์› ๊ฐ€์ž… ์ฒ˜๋ฆฌ ์„ฑ๊ณต ์‹œ, ๋กœ๊ทธ์ธ ์š”์ฒญ ํ›„ ๋ฉ”์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

์ด์ „ ์ฝ”๋“œ

int result = userService.join(user); if( result > 0 ) { return "redirect:/login"; }
Java
๋ณต์‚ฌ

์ˆ˜์ • ์ฝ”๋“œ

// ์•”ํ˜ธํ™” ์ „ ๋น„๋ฐ€๋ฒˆํ˜ธ String plainPassword = user.getPassword(); // ํšŒ์› ๊ฐ€์ž… ์š”์ฒญ int result = userService.join(user); // ํšŒ์› ๊ฐ€์ž… ์„ฑ๊ณต ์‹œ, ๋ฐ”๋กœ ๋กœ๊ทธ์ธ if( result > 0 ) { // ์•”ํ˜ธํ™” ์ „ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋‹ค์‹œ ์„ธํŒ… // ํšŒ์›๊ฐ€์ž… ์‹œ, ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, user.setPassword(plainPassword); userService.login(user); return "redirect:/"; }
Java
๋ณต์‚ฌ

HomeController.java

@Slf4j @Controller public class HomeController { @Autowired private UserService userService; //** * ๋ฉ”์ธ ํ™”๋ฉด * ๐Ÿ”— [GET] - / * ๐Ÿ“„ index.html * @return * @throws Exception */ @GetMapping("") // public String home(Principal principal, Model model) throws Exception { // public String home(Authentication authentication, Model model) throws Exception { public String home(@AuthenticationPrincipal User authUser, Model model) throws Exception { log.info(":::::::::: ๋ฉ”์ธ ํ™”๋ฉด ::::::::::"); // if( authentication != null ) { // User authAuth = (User) authentication.getPrincipal(); // String username = authAuth.getUsername(); // log.info("username : " + username); // Users user = userService.select(username); // ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ // log.info("user : " + user); // model.addAttribute("user", user); // } // if (principal != null) { // String username = principal.getName(); // ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์•„์ด๋”” // log.info("username : " + username); // Users user = userService.select(username); // ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ // log.info("user : " + user); // model.addAttribute("user", user); // ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋ชจ๋ธ์— ๋“ฑ๋ก // } else { // log.info("principal is null"); // } if( authUser != null ) { String username = authUser.getUsername(); // ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์•„์ด๋”” log.info("username : " + username); Users user = userService.select(username); // ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ log.info("user : " + user); model.addAttribute("user", user); // ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋ชจ๋ธ์— ๋“ฑ๋ก log.info("authAuth : " + authUser); } return "index"; } /** * ํšŒ์› ๊ฐ€์ž… ํ™”๋ฉด * ๐Ÿ”— [GET] - /join * ๐Ÿ“„ join.html * @return */ @GetMapping("/join") public String join() { log.info(":::::::::: ํšŒ์› ๊ฐ€์ž… ํ™”๋ฉด ::::::::::"); return "join"; } /** * ํšŒ์› ๊ฐ€์ž… ์ฒ˜๋ฆฌ * ๐Ÿ”— [POST] - /join * โžก โญ• ๐Ÿ”„๐Ÿ”๋ฐ”๋กœ ๋กœ๊ทธ์ธ โžก / * โŒ /join?error * @param user * @return * @throws Exception */ @PostMapping("/join") public String joinPro(Users user) throws Exception { log.info(":::::::::: ํšŒ์› ๊ฐ€์ž… ์ฒ˜๋ฆฌ ::::::::::"); log.info("user : " + user); // ์•”ํ˜ธํ™” ์ „ ๋น„๋ฐ€๋ฒˆํ˜ธ String plainPassword = user.getPassword(); // ํšŒ์› ๊ฐ€์ž… ์š”์ฒญ int result = userService.join(user); // ํšŒ์› ๊ฐ€์ž… ์„ฑ๊ณต ์‹œ, ๋ฐ”๋กœ ๋กœ๊ทธ์ธ if( result > 0 ) { // ์•”ํ˜ธํ™” ์ „ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋‹ค์‹œ ์„ธํŒ… // ํšŒ์›๊ฐ€์ž… ์‹œ, ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, user.setPassword(plainPassword); userService.login(user); return "redirect:/"; } return "redirect/join?error"; } /** * ์•„์ด๋”” ์ค‘๋ณต ๊ฒ€์‚ฌ * @param username * @return * @throws Exception */ @ResponseBody @GetMapping("/check/{username}") public ResponseEntity<Boolean> userCheck(@PathVariable("username") String username) throws Exception { log.info("์•„์ด๋”” ์ค‘๋ณต ํ™•์ธ : " + username); Users user = userService.select(username); // ์•„์ด๋”” ์ค‘๋ณต if( user != null ) { log.info("์ค‘๋ณต๋œ ์•„์ด๋”” ์ž…๋‹ˆ๋‹ค - " + username); return new ResponseEntity<>(false, HttpStatus.OK); } // ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์•„์ด๋””์ž…๋‹ˆ๋‹ค. log.info("์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์•„์ด๋”” ์ž…๋‹ˆ๋‹ค." + username); return new ResponseEntity<>(true, HttpStatus.OK); } }
Java
๋ณต์‚ฌ

์‚ฌ์šฉ์ž ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ

Principal vs Authentication vs User

์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ฃผ์š” ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ ํด๋ž˜์Šค
๋‹ค์Œ์€ Spring Security์˜ ์ฃผ์š” ์ธํ„ฐํŽ˜์ด์Šค์™€ ํด๋ž˜์Šค์˜ ๊ตฌ์กฐ๋„์ž…๋‹ˆ๋‹ค
java.security.Principal (Interface) โ†‘ Authentication (Interface) โ†‘ UsernamePasswordAuthenticationToken (๊ตฌํ˜„์ฒด) โ†‘ getPrincipal() โ†ณ org.springframework.security.core.userdetails.User (implements UserDetails)
Java
๋ณต์‚ฌ
์ด ๊ตฌ์กฐ๋„๋Š” Spring Security์—์„œ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ณ„์ธตํ™”๋˜์–ด ์žˆ๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
Principal์€ ์ตœ์ƒ์œ„ ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฉฐ, Authentication์€ ์ด๋ฅผ ํ™•์žฅํ•˜์—ฌ ๋” ๋งŽ์€ ์ธ์ฆ ๊ด€๋ จ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. UsernamePasswordAuthenticationToken์€ Authentication์˜ ๊ตฌํ˜„์ฒด ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ, getPrincipal() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด UserDetails๋ฅผ ๊ตฌํ˜„ํ•œ User ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
ํด๋ž˜์Šค/์ธํ„ฐํŽ˜์ด์Šค
์—ญํ• 
์ฃผ์š” ๋ฉ”์„œ๋“œ
์ฃผ์š” ๊ตฌํ˜„์ฒด
Principal
์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ๊ธฐ๋ณธ ์ •๋ณด ์ œ๊ณต (ํ‘œ์ค€ ์ž๋ฐ” ์ธํ„ฐํŽ˜์ด์Šค)
getName()
Spring Security์˜ User, ๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ๊ฐ์ฒด
Authentication
Spring Security ์ธ์ฆ ์ •๋ณด (์‚ฌ์šฉ์ž, ๊ถŒํ•œ, ์ธ์ฆ ์ƒํƒœ ๋“ฑ ํฌํ•จ)
getPrincipal(), getAuthorities(), isAuthenticated()
UsernamePasswordAuthenticationToken, JwtAuthenticationToken
User
์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ์„ธ๋ถ€ ์ •๋ณด ์ œ๊ณต (Spring Security์˜ ๊ตฌํ˜„์ฒด, UserDetails๋ฅผ ๊ตฌํ˜„)
getUsername(), getAuthorities(), isAccountNonLocked() ๋“ฑ
Spring Security ๊ธฐ๋ณธ User ํด๋ž˜์Šค
โ€ข
Principal: ์ตœ์†Œํ•œ์˜ ์‚ฌ์šฉ์ž ์‹๋ณ„ ์ •๋ณด๋ฅผ ์ œ๊ณต.
โ€ข
Authentication: ์ธ์ฆ ๋ฐ ๊ถŒํ•œ ๊ด€๋ จ ์ •๋ณด๋ฅผ ๋ชจ๋‘ ํฌํ•จ.
โ€ข
User: Spring Security์—์„œ ์‚ฌ์šฉ์ž ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„์ฒด.