๐Ÿ”ฅ #10ใ‚นใƒ—ใƒชใƒณใ‚ฐๅฎ‰ๅ…จ็™ป้Œฒใ‚’่กŒใ†


๐Ÿ”ฅ #็ถšใ„ใฆ8่กŒใ„ใพใ™~!

UserApi Controlใ‹ใ‚‰่ฆ‹ใ‚‹ใจใ€/auth/loginProcใฏไฝœๆˆใ•ใ‚Œใฆใ„ใพใ›ใ‚“.
ใ‚นใƒ—ใƒชใƒณใ‚ฐๅฎ‰ๅ…จๅผใŒ้ฎๆ–ญใ•ใ‚Œใ‚‹ใ‹ใ‚‰ใงใ™.
ใƒ–ใƒญใƒƒใ‚ฏใ™ใ‚‹ใซใฏใ€SecurityConfigใฎconfigureใƒกใ‚ฝใƒƒใƒ‰ใซ.loginProcessingUrl("/auth/loginProc")ใ‚’่ฟฝๅŠ ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™.
ใ—ใŸใŒใฃใฆใ€็พๅœจใฎSecurityConfigใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™.
< SecurityConfig >
@Configuration // ๋นˆ ๋“ฑ๋ก (IoC๊ด€๋ฆฌ)
@EnableWebSecurity // Security ํ•„ํ„ฐ๊ฐ€ ๋“ฑ๋ก๋จ = ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ์ด๋ฏธ ํ™œ์„ฑํ™”๋Š” ๋˜์–ด์žˆ์ง€๋งŒ, ์„ค์ •์€ ํ•ด๋‹น ํŒŒ์ผ์—์„œ ํ•  ๊ฒƒ์ž„
@EnableGlobalMethodSecurity(prePostEnabled = true) // ํŠน์ • ์ฃผ์†Œ๋กœ ์ ‘๊ทผ์„ ํ•˜๋ฉด ๊ถŒํ•œ ๋ฐ ์ธ์ฆ์„ ๋ฏธ๋ฆฌ ์ฒดํฌ (์ˆ˜ํ–‰ํ•œ ํ›„์— ์ฒดํฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹˜)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // 1. Bean ์–ด๋…ธํ…Œ์ด์…˜์€ ๋ฉ”์„œ๋“œ์— ๋ถ™์—ฌ์„œ ๊ฐ์ฒด ์ƒ์„ฑ์‹œ ์‚ฌ์šฉ
    @Bean // IoC๊ฐ€ ๋œ๋‹ค.
    public BCryptPasswordEncoder encodePWD() {
        return new BCryptPasswordEncoder(); // ์ด ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง์ด ๊ด€๋ฆฌํ•˜๊ฒŒ ๋จ. ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ€์ ธ๊ฐ€์„œ ์“ฐ๋ฉด ๋œ๋‹ค.
    }

    // ํ•„ํ„ฐ๋ง
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable() // csrf ํ† ํฐ ๋น„ํ™œ์„ฑํ™” (ํ…Œ์ŠคํŠธ์‹œ ๊ฑธ์–ด๋‘๋Š”๊ฒŒ ์ข‹์Œ)
                .authorizeRequests() // request๊ฐ€ ๋“ค์–ด์˜ค๋ฉด
                .antMatchers("/", "/auth/**", "/js/**", "/css/**", "/image/**") // ์—ฌ๊ธฐ๋กœ ๋“ค์–ด์˜ค๋ฉด
                .permitAll() // ๋ชจ๋‘ ๊ฐ€๋Šฅ (๋ˆ„๊ตฌ๋‚˜ ๊ฐ€๋Šฅ)
                .anyRequest() // ๊ทธ๊ฒŒ ์•„๋‹Œ ๋‹ค๋ฅธ ๋ชจ๋“  ์š”์ฒญ์€
                .authenticated() // ์ธ์ฆ์ด ๋˜์–ด์•ผ ํ•œ๋‹ค
                .and()
                .formLogin()
                .loginPage("/auth/loginForm") // ์ธ์ฆ์ด ํ•„์š”ํ•œ ์š”์ฒญ์€ ์ด ๋กœ๊ทธ์ธ ํผ์œผ๋กœ ์˜จ๋‹ค
                .loginProcessingUrl("/auth/loginProc") // ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ํ•ด๋‹น ์ฃผ์†Œ๋กœ ์š”์ฒญ์ด ์˜ค๋Š” ๋กœ๊ทธ์ธ์„ ๊ฐ€๋กœ์ฑ„์„œ ๋Œ€์‹  ๋กœ๊ทธ์ธ์„ ํ•œ๋‹ค.
                .defaultSuccessUrl("/"); // ๋กœ๊ทธ์ธ ์„ฑ๊ณตํ•˜๋ฉด "/"๋กœ ๊ฐ„๋‹ค.
//                .failureUrl("/fail"); // ์‹คํŒจ์‹œ url
    }

    // ์ฐธ๊ณ  : .headers().frameOptions().disable() // ์•„์ดํ”„๋ ˆ์ž„ ์ ‘๊ทผ ๋ง‰๊ธฐ
    // ์ฐธ๊ณ  : .csrf().disable() // csrf ํ† ํฐ ๋น„ํ™œ์„ฑํ™” (ํ…Œ์ŠคํŠธ์‹œ ๊ฑธ์–ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹์Œ)
}
Spring securityใฏใ€ใƒฆใƒผใ‚ถใƒผใŒ่ฆๆฑ‚ใ—ใŸใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ใƒ–ใƒญใƒƒใ‚ฏใ—ใฆใƒญใ‚ฐใ‚คใƒณใ—ใพใ™.
UserDetailsใ‚ฟใ‚คใƒ—ใฎUserใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™.
ใƒญใ‚ฐใ‚คใƒณใŒๅฎŒไบ†ใ™ใ‚‹ใจSpring Securityใ‚ปใƒƒใ‚ทใƒงใƒณใซใƒฆใƒผใ‚ถใƒผๆƒ…ๅ ฑใ‚’็™ป้Œฒใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใŒใ€ใƒฆใƒผใ‚ถใƒผใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’็™ป้Œฒใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“.UserDetailsใ‚ฟใ‚คใƒ—ใฎใฟ็™ป้Œฒใงใใพใ™.
< PrincipalDetail >
// ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ๋กœ๊ทธ์ธ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„์„œ ๋กœ๊ทธ์ธ์„ ์ง„ํ–‰ํ•˜๊ณ  ์™„๋ฃŒ๊ฐ€ ๋˜๋ฉด,
// UserDetails ํƒ€์ž…์˜ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์˜ ๊ณ ์œ ํ•œ ์„ธ์…˜ ์ €์žฅ์†Œ์— ์ €์žฅํ•œ๋‹ค.
public class PrincipalDetail implements UserDetails {
    private User user; // ์ฝคํฌ์ง€์…˜ (๊ฐ์ฒด๋ฅผ ํ’ˆ๊ณ  ์žˆ๋Š” ๊ฒƒ)

    public PrincipalDetail(User user) {
        this.user = user;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    // ๊ณ„์ •์ด ๋งŒ๋ฃŒ๋˜์ง€ ์•Š์•˜๋Š”์ง€ ๋ฆฌํ„ดํ•œ๋‹ค. (true : ๋งŒ๋ฃŒ ์•ˆ๋จ)
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    // ๊ณ„์ •์ด ์ž ๊ฒจ์žˆ๋Š”์ง€ ์•ˆ ์ž ๊ฒจ์žˆ๋Š”์ง€ ๋ฆฌํ„ดํ•œ๋‹ค. (true : ์ž ๊ธฐ์ง€ ์•Š์Œ)
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    // ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋งŒ๋ฃŒ๋˜์ง€ ์•Š์•˜๋Š”์ง€๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค. (true : ๋งŒ๋ฃŒ ์•ˆ๋จ)
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    // ๊ณ„์ •์ด ํ™œ์„ฑํ™”(์‚ฌ์šฉ๊ฐ€๋Šฅ)์ธ์ง€ ๋ฆฌํ„ดํ•œ๋‹ค. (true : ํ™œ์„ฑํ™”)
    @Override
    public boolean isEnabled() {
        return true;
    }

    // ๊ณ„์ •์ด ๊ฐ–๊ณ ์žˆ๋Š” ๊ถŒํ•œ ๋ชฉ๋ก์„ ๋ฆฌํ„ดํ•œ๋‹ค. (๊ถŒํ•œ์ด ์—ฌ๋Ÿฌ๊ฐœ ์žˆ์„ ์ˆ˜ ์žˆ์–ด์„œ ๋ฃจํ”„๋ฅผ ๋Œ์•„์•ผ ํ•˜๋Š”๋ฐ ํ˜„์žฌ๋Š” ํ•˜๋‚˜๋งŒ)
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {

        Collection<GrantedAuthority> collectors = new ArrayList<>(); // ArrayList๋Š” Collection ํƒ€์ž…์ด๋‹ค. (์ƒ์†)

//        collectors.add(new GrantedAuthority() {
//
//            @Override
//            public String getAuthority() {
//                return "ROLE_"+user.getRole(); // role ์„ ๋ฐ›์„ ๋•Œ ์•ž์— "ROLE_" ๋ถ™์ด๋Š” ๊ฒƒ(prefix)์ด ์Šคํ”„๋ง์˜ ๊ทœ์น™, ์ฆ‰ ROLE_USER ๊ฐ™์€ ์‹์œผ๋กœ ๋ฆฌํ„ด๋จ
//            }
//        });

        collectors.add(()->{return "ROLE_"+ user.getRole();}); // ์–ด์ฐจํ”ผ add ์•ˆ์— ๋“ค์–ด๊ฐˆ ํ•จ์ˆ˜๋Š” GrantedAuthority() ๋ฟ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋žŒ๋‹ค์‹์œผ๋กœ ๊ฐ€๋Šฅ

        return collectors;
    }

}
PrincipalDetailใ‚’ใ‚ปใƒƒใ‚ทใƒงใƒณใซไฟๅญ˜ใ—ใพใ™.ใ“ใฎๆ™‚็‚นใงใ€DBใซๆ ผ็ดใ•ใ‚Œใฆใ„ใ‚‹Userใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚‚ๅซใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚ใ€ใ‚ณใƒณใƒ‘ใ‚คใƒซใ‚’่กŒใ„ใพใ™.
ใ‚ฟใ‚คใƒ—ใฏUserDetailsใงใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใฎใงใ€ใใ‚Œใ‚’ๅฎŸ็พใ—ใพใ™.
UserDetailsใŒๆŽก็”จใ—ใฆใ„ใ‚‹ใ™ในใฆใฎๆŠฝ่ฑก็š„ใชๆ–นๆณ•ใŒไธŠๆ›ธใใ•ใ‚Œใฆใ„ใพใ™.
ใ‚ณใƒณใƒใ‚ธใƒƒใƒˆใ‚ณใƒณใ‚ปใƒ—ใƒˆ
// ์ปดํฌ์ง€์…˜
public class PrincipalDetail {
    private User user; // ์ฝคํฌ์ง€์…˜ (๊ฐ์ฒด๋ฅผ ํ’ˆ๊ณ  ์žˆ๋Š” ๊ฒƒ) }
    
// ์ƒ์†
public class PrincipalDetail extends User { }
- ์ƒ์† - 'IS-A' ๊ด€๊ณ„
- ์ปดํฌ์ง€์…˜ - 'HAS-A' ๊ด€๊ณ„
- DI - ?????

'IS-A', 'HAS-A' ๊ด€๊ณ„๋Š” ์ƒ์†, ์œ„์ž„์„ **์ •์ ์ธ ํด๋ž˜์Šค** ๊ด€๊ณ„์—์„œ ์„ค๋ช…ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.
**DI**๋Š” 'HAS-A' ๊ด€๊ณ„์—์„œ **๋™์ ์œผ๋กœ ๋Œ€์ƒ ๊ฐ์ฒด๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ๋ฒ•**์— ๋Œ€ํ•œ ๊ฒƒ์ด๋‹ค.

์ฆ‰, 'HAS-A' ๊ด€๊ณ„๋กœ ๋ณด๋ฉด ์ธํ„ฐํŽ˜์ด์Šค(์ถ”์ƒ ํด๋ž˜์Šค)์— ์˜์กดํ•˜๋„๋ก ๊ด€๊ณ„๋ฅผ ๋งบ๋Š” ๊ฒƒ๊นŒ์ง€ ์ธ๋ฐ, DI๋Š” ์—ฌ๊ธฐ์— ์ถ”๊ฐ€ํ•ด์„œ ๋™์ ์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ๋ฒ•๊นŒ์ง€๋ฅผ ์ด์•ผ๊ธฐํ•œ๋‹ค.
< PrincipalDetailService >
@Service // Bean ๋“ฑ๋ก
public class PrincipalDetailService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    // ์Šคํ”„๋ง์ด ๋กœ๊ทธ์ธ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑŒ ๋•Œ, username๊ณผ password ๋ณ€์ˆ˜ 2๊ฐœ๋ฅผ ๊ฐ€๋กœ์ฑ”
    // password ์ฒ˜๋ฆฌ๋Š” ์Šคํ”„๋ง์ด ์•Œ์•„์„œ ํ•จ
    // ๋‚˜๋Š” username์ด ํ•ด๋‹น DB์— ์žˆ๋Š”์ง€๋งŒ ํ™•์ธํ•ด์„œ ๋ฆฌํ„ดํ•ด์ฃผ๋ฉด ๋จ
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User principal = userRepository.findByUsername(username) // Optional ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— .orElseThrow
                .orElseThrow(()->{
                    return new UsernameNotFoundException("ํ•ด๋‹น ์‚ฌ์šฉ์ž๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." + username);
                });

        return new PrincipalDetail(principal); // ์ด๋•Œ ์‹œํ๋ฆฌํ‹ฐ ์„ธ์…˜์— ์œ ์ €์ •๋ณด ์ €์žฅ๋จ
    }
}
็ถ™ๆ‰ฟใ‚ฟใ‚คใƒ—ใฏUserDetailServiceใงใ™.
ไธŠๆ›ธใใ•ใ‚ŒใŸloadUserByUsername้–ขๆ•ฐใงใ€ๅˆ‡ใ‚Šๅ–ใฃใŸใƒฆใƒผใ‚ถใƒผๅๅค‰ๆ•ฐใŒDBใซใ‚ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใพใ™.
ใƒญใ‚ฐใ‚คใƒณใ‚’่ฆๆฑ‚ใ™ใ‚‹ใจใ€loadUserByUsername้–ขๆ•ฐใŒ่‡ชๅ‹•็š„ใซๅฎŸ่กŒใ•ใ‚Œใ€ใƒฆใƒผใ‚ถใƒผๅใซๅฏพๅฟœใ™ใ‚‹ใƒฆใƒผใ‚ถใƒผใŒๆคœ็ดขใ•ใ‚Œใ€PrincipalDetailใ‚ฟใ‚คใƒ—(ใ™ใชใ‚ใกใ€UserDetailsใ‚ฟใ‚คใƒ—)ใŒ่ฟ”ใ•ใ‚Œใพใ™.
->ใƒฆใƒผใ‚ถDetailsใ‚ฟใ‚คใƒ—ใงใ‚ใ‚‹ใŸใ‚ใ€ใƒฆใƒผใ‚ถๆƒ…ๅ ฑใฏใ‚ปใ‚ญใƒฅใ‚ขใ‚ปใƒƒใ‚ทใƒงใƒณใซๆ ผ็ดใ•ใ‚Œใพใ™.
ใ“ใฎ้–ขๆ•ฐใฏ้Žๅ‰ฐใซๅฎŸ็พใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹.ใ“ใ‚Œใง็งใŸใกใฏๆœฌๅฝ“ใซ(?)ใƒฆใƒผใ‚ถใƒผๆƒ…ๅ ฑใ‚’ๅซใ‚ใฆใƒชใ‚ฟใƒผใƒณใงใใพใ™.
< UserRepository >
public interface UserRepository extends JpaRepository<User, Integer> {

    // SELECT * FROM user WHERE username = 1?;
    Optional<User> findByUsername(String username);
}
findByUsernameใŒใชใ„ใŸใ‚ใ€UserRepositoryใซใ‚ˆใฃใฆไฝœๆˆใ•ใ‚Œใพใ™.(ๅ‘ฝๅ่ฆๅ‰‡)
    // ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ๋Œ€์‹  ๋กœ๊ทธ์ธ ํ•จ -> password ๊ฐ€๋กœ์ฑ”
    // ๊ฐ€๋กœ์ฑˆ password๊ฐ€ ํšŒ์›๊ฐ€์ž… ๋  ๋•Œ ๋ฌด์—‡์œผ๋กœ ํ•ด์‰ฌ๊ฐ€ ๋˜์—ˆ๋Š”์ง€ ์•Œ์•„์•ผํ•จ -> ๊ทธ๋ž˜์•ผ ๊ฐ™์€ ํ•ด์‰ฌ๋กœ ์•”ํ˜ธํ™” ํ•˜๊ณ  DB์— ์žˆ๋Š” ํ•ด์‰ฌ์™€ ๋น„๊ตํ•˜์—ฌ ๋กœ๊ทธ์ธ
    // ์ฆ‰, ํŒจ์Šค์›Œ๋“œ ๋น„๊ตํ•˜๋Š” ๋ฉ”์„œ๋“œ
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(principalDetailService).passwordEncoder(encodePWD()); // passwordEncoder ํ•˜๋Š” ์• ๊ฐ€ encodePWD ์ž„.
    }
ใ“ใ“ใงใฏ,็™ป้Œฒใ—ใŸใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’็ฌฆๅทๅŒ–ๆฏ”่ผƒใ™ใ‚‹.
<ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃๆง‹ๆˆ>ๆœ€็ต‚็‰ˆ
@Configuration // ๋นˆ ๋“ฑ๋ก (IoC๊ด€๋ฆฌ)
@EnableWebSecurity // Security ํ•„ํ„ฐ๊ฐ€ ๋“ฑ๋ก๋จ = ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ์ด๋ฏธ ํ™œ์„ฑํ™”๋Š” ๋˜์–ด์žˆ์ง€๋งŒ, ์„ค์ •์€ ํ•ด๋‹น ํŒŒ์ผ์—์„œ ํ•  ๊ฒƒ์ž„
@EnableGlobalMethodSecurity(prePostEnabled = true) // ํŠน์ • ์ฃผ์†Œ๋กœ ์ ‘๊ทผ์„ ํ•˜๋ฉด ๊ถŒํ•œ ๋ฐ ์ธ์ฆ์„ ๋ฏธ๋ฆฌ ์ฒดํฌ (์ˆ˜ํ–‰ํ•œ ํ›„์— ์ฒดํฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹˜)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PrincipalDetailService principalDetailService;

    // 1. Bean ์–ด๋…ธํ…Œ์ด์…˜์€ ๋ฉ”์„œ๋“œ์— ๋ถ™์—ฌ์„œ ๊ฐ์ฒด ์ƒ์„ฑ์‹œ ์‚ฌ์šฉ
    @Bean // IoC๊ฐ€ ๋œ๋‹ค.
    public BCryptPasswordEncoder encodePWD() {
        return new BCryptPasswordEncoder(); // ์ด ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง์ด ๊ด€๋ฆฌํ•˜๊ฒŒ ๋จ. ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ€์ ธ๊ฐ€์„œ ์“ฐ๋ฉด ๋œ๋‹ค.
    }

    // 2. ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ๋กœ๊ทธ์ธํ•  ๋•Œ ์–ด๋–ค ์•”ํ˜ธํ™”๋กœ ์ธ์ฝ”๋”ฉํ•ด์„œ ๋น„๋ฒˆ์„ ๋น„๊ตํ• ์ง€ ์•Œ๋ ค์ค˜์•ผ ํ•จ.
    // ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ๋Œ€์‹  ๋กœ๊ทธ์ธ ํ•จ -> password ๊ฐ€๋กœ์ฑ”
    // ๊ฐ€๋กœ์ฑˆ password๊ฐ€ ํšŒ์›๊ฐ€์ž… ๋  ๋•Œ ๋ฌด์—‡์œผ๋กœ ํ•ด์‰ฌ๊ฐ€ ๋˜์—ˆ๋Š”์ง€ ์•Œ์•„์•ผํ•จ -> ๊ทธ๋ž˜์•ผ ๊ฐ™์€ ํ•ด์‰ฌ๋กœ ์•”ํ˜ธํ™” ํ•˜๊ณ  DB์— ์žˆ๋Š” ํ•ด์‰ฌ์™€ ๋น„๊ตํ•˜์—ฌ ๋กœ๊ทธ์ธ
    // ์ฆ‰, ํŒจ์Šค์›Œ๋“œ ๋น„๊ตํ•˜๋Š” ๋ฉ”์„œ๋“œ
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(principalDetailService).passwordEncoder(encodePWD()); // passwordEncoder ํ•˜๋Š” ์• ๊ฐ€ encodePWD ์ž„.
    }

    // 3. ํ•„ํ„ฐ๋ง
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable() // csrf ํ† ํฐ ๋น„ํ™œ์„ฑํ™” (ํ…Œ์ŠคํŠธ์‹œ ๊ฑธ์–ด๋‘๋Š”๊ฒŒ ์ข‹์Œ)
                .authorizeRequests() // request๊ฐ€ ๋“ค์–ด์˜ค๋ฉด
                .antMatchers("/", "/auth/**", "/js/**", "/css/**", "/image/**") // ์—ฌ๊ธฐ๋กœ ๋“ค์–ด์˜ค๋ฉด
                .permitAll() // ๋ชจ๋‘ ๊ฐ€๋Šฅ (๋ˆ„๊ตฌ๋‚˜ ๊ฐ€๋Šฅ)
                .anyRequest() // ๊ทธ๊ฒŒ ์•„๋‹Œ ๋‹ค๋ฅธ ๋ชจ๋“  ์š”์ฒญ์€
                .authenticated() // ์ธ์ฆ์ด ๋˜์–ด์•ผ ํ•œ๋‹ค
                .and()
                .formLogin()
                .loginPage("/auth/loginForm") // ์ธ์ฆ์ด ํ•„์š”ํ•œ ์š”์ฒญ์€ ์ด ๋กœ๊ทธ์ธ ํผ์œผ๋กœ ์˜จ๋‹ค
                .loginProcessingUrl("/auth/loginProc") // ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ํ•ด๋‹น ์ฃผ์†Œ๋กœ ์š”์ฒญ์ด ์˜ค๋Š” ๋กœ๊ทธ์ธ์„ ๊ฐ€๋กœ์ฑ„์„œ ๋Œ€์‹  ๋กœ๊ทธ์ธ์„ ํ•œ๋‹ค.
                .defaultSuccessUrl("/"); // ๋กœ๊ทธ์ธ ์„ฑ๊ณตํ•˜๋ฉด "/"๋กœ ๊ฐ„๋‹ค.
//                .failureUrl("/fail"); // ์‹คํŒจ์‹œ url
    }

    // ์ฐธ๊ณ  : .headers().frameOptions().disable() // ์•„์ดํ”„๋ ˆ์ž„ ์ ‘๊ทผ ๋ง‰๊ธฐ
    // ์ฐธ๊ณ  : .csrf().disable() // csrf ํ† ํฐ ๋น„ํ™œ์„ฑํ™” (ํ…Œ์ŠคํŠธ์‹œ ๊ฑธ์–ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹์Œ)
}
ใ“ใ‚Œใ‚’่กŒใ†ใจใ€Spring Securityใ‚ปใƒƒใ‚ทใƒงใƒณใซใƒฆใƒผใ‚ถใƒผๆƒ…ๅ ฑใŒไฟๅญ˜ใ•ใ‚Œใพใ™.
UserDetailใ‚ฟใ‚คใƒ—ใงPrincipalDetailใ‚’ไฝœๆˆใ—ใ€PrincipalDetailใ‚’ไฝฟ็”จใ—ใฆใƒ‘ใƒƒใ‚ฑใƒผใ‚ธๅŒ–ใ—ใฆไฟๅญ˜ใ—ใพใ™.
ใงใฏใ€spring securityใŒไฝœๆˆใ—ใŸใ‚ปใƒƒใ‚ทใƒงใƒณๆƒ…ๅ ฑใ‚’ใ‚ณใƒณใƒˆใƒญใƒผใƒฉใงๆคœ็ดขใ™ใ‚‹ใซใฏใฉใ†ใ™ใ‚Œใฐใ„ใ„ใฎใงใ—ใ‚‡ใ†ใ‹.
  • ใ‚ณใƒณใƒˆใƒญใƒผใƒฉใ‹ใ‚‰ใƒญใ‚ฐใ‚คใƒณใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ๆคœ็ดข:@่ช่จผPrincipal Principal
  •    @GetMapping({"", "/"})
        public String index(@AuthenticationPrincipal PrincipalDetail principal) { // ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋กœ๊ทธ์ธ ๋œ ์„ธ์…˜์„ ์ฐพ๋Š” ๋ฐฉ์‹ : @AuthenticationPrincipal PrincipalDetail principal
            // /WEB-INF/views/index.jsp
            System.out.println("๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž ์•„์ด๋””:"+principal.getUsername());
            return "index";
        }
    ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆPrincipalDetail principalใ‚’ๅ…ฅๅŠ›ใ—ใพใ™.@Autowired private PrincipalDetail principal;ใ‚’ไพๅญ˜ๆณจๅ…ฅๆ–นๅผใงๆณจๅ…ฅใ™ใ‚‹ใ“ใจใฏไธๅฏ่ƒฝใงใ‚ใ‚‹.