html
์คํ๋ง ๋ถํธ ์ ํ๋ฆฌ์ผ์ด์ ์์ Spring Security ๋ก๊ทธ์ธ ๊ตฌํ ๋ฐ ๋๋ฒ๊น
๋ชฉ์ฐจ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
1. <a href="#introduction-to-spring-security-login">Spring Security ๋ก๊ทธ์ธ ์๊ฐ</a> ..........................................................................................................................................1 2. <a href="#common-issues-in-spring-security-login-implementation">Spring Security ๋ก๊ทธ์ธ ๊ตฌํ์ ์ผ๋ฐ์ ์ธ ๋ฌธ์ </a> ............................................................................................................................2 2.1. <a href="#ui-issues-fixing-the-login-page">UI ๋ฌธ์ : ๋ก๊ทธ์ธ ํ์ด์ง ์์ </a> ...........................................................................................................................................2 2.2. <a href="#backend-issues-missing-name-attributes-in-form-elements">๋ฐฑ์๋ ๋ฌธ์ : ํผ ์์์ 'name' ์์ฑ ๋๋ฝ</a> ..................................................................................................................................................3 3. <a href="#implementing-userdetailservice-in-spring-security">Spring Security์์ UserDetailsService ๊ตฌํ</a> .........................................................................................................................................4 3.1. <a href="#overview-of-userdetailservice">UserDetailsService ๊ฐ์</a> ........................................................................................................................................4 3.2. <a href="#implementing-loaduserbyusername-method">loadUserByUsername ๋ฉ์๋ ๊ตฌํ</a> ........................................................................................................................................5 4. <a href="#handling-granted-authorities-and-roles-in-spring-security">Spring Security์์ ๋ถ์ฌ๋ ๊ถํ ๋ฐ ์ญํ ์ฒ๋ฆฌ</a> ...................................................................................................................................................6 4.1. <a href="#understanding-granted-authority">๋ถ์ฌ๋ ๊ถํ ์ดํด</a> ........................................................................................................................................6 4.2. <a href="#configuring-granted-authorities">๋ถ์ฌ๋ ๊ถํ ๊ตฌ์ฑ</a> ........................................................................................................................................7 5. <a href="#debugging-spring-security-login-errors">Spring Security ๋ก๊ทธ์ธ ์ค๋ฅ ๋๋ฒ๊น
</a> ........................................................................................................................................8 5.1. <a href="#common-errors-and-their-causes">์ผ๋ฐ์ ์ธ ์ค๋ฅ ๋ฐ ์์ธ</a> ..........................................................................................................................................8 5.2. <a href="#debugging-techniques-in-spring-boot">Spring Boot์์์ ๋๋ฒ๊น
๊ธฐ์ </a> ..........................................................................................................................................9 6. <a href="#testing-the-login-functionality">๋ก๊ทธ์ธ ๊ธฐ๋ฅ ํ
์คํธ</a> ..................................................................................................................................................10 6.1. <a href="#running-the-application-in-debug-mode">๋๋ฒ๊ทธ ๋ชจ๋์์ ์ ํ๋ฆฌ์ผ์ด์
์คํ</a> ..........................................................................................................................................10 6.2. <a href="#verifying-successful-login">์ฑ๊ณต์ ์ธ ๋ก๊ทธ์ธ ํ์ธ</a> ........................................................................................................................................................11 7. <a href="#conclusion-and-best-practices">๊ฒฐ๋ก ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก</a> ................................................................................................................................................12 |
Spring Security ๋ก๊ทธ์ธ ์๊ฐ
Spring Security๋ Spring ์ํ๊ณ๋ฅผ ์ํ ๊ฐ๋ ฅํ๊ณ ๋์ ์์ค์ผ๋ก ์ฌ์ฉ์ ์ ์ ๊ฐ๋ฅํ ์ธ์ฆ ๋ฐ ์ ๊ทผ ์ ์ด ํ๋ ์์ํฌ์ ๋๋ค. ์์ ํ ๋ก๊ทธ์ธ ๋ฉ์ปค๋์ฆ์ ๊ตฌํํ๋ ๊ฒ์ ๋ชจ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉ์ ๋ฐ์ดํฐ์ ๊ธฐ๋ฅ์ด ๋ฌด๋จ ์ก์ธ์ค๋ก๋ถํฐ ๋ณดํธ๋๋๋ก ๋ณด์ฅํ๋ ๋ฐ ์ค์ํฉ๋๋ค. ์ด eBook์ Spring Boot ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ Spring Security ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ์ค์ ํ๊ณ ๋๋ฒ๊น ํ๋ ๋ณต์กํ ๊ณผ์ ์ ํ๊ตฌํฉ๋๋ค.
๊ฐ์
์ด ๊ฐ์ด๋์์๋ ๋ค์์ ๋ฐฐ์ฐ๊ฒ ๋ฉ๋๋ค:
- ๋ก๊ทธ์ธ ๊ตฌํ๊ณผ ๊ด๋ จ๋ ์ผ๋ฐ์ ์ธ UI ๋ฐ ๋ฐฑ์๋ ๋ฌธ์ ํด๊ฒฐ
- UserDetailsService ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์ฌ ์ฌ์ฉ์ ์ธ์ฆ ์ฒ๋ฆฌ
- ์ฌ์ฉ์ ๊ถํ ๊ด๋ฆฌ๋ฅผ ์ํ ๋ถ์ฌ๋ ๊ถํ ๋ฐ ์ญํ ๊ตฌ์ฑ
- ๋ก๊ทธ์ธ ๊ด๋ จ ์ค๋ฅ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ํจ๊ณผ์ ์ธ ๋๋ฒ๊น ๊ธฐ๋ฒ ํ์ฉ
- ๋งค๋๋ฌ์ด ์ฌ์ฉ์ ๊ฒฝํ์ ๋ณด์ฅํ๊ธฐ ์ํ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ํ ์คํธ ๋ฐ ๊ฒ์ฆ
์ค์์ฑ ๋ฐ ๋ชฉ์
๊ฐ๋ ฅํ ๋ณด์ ์์คํ ์ ๊ตฌํํ๋ ๊ฒ์ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ๋ณดํธํ๊ณ ์ฌ์ฉ์ ์ ๋ขฐ๋ฅผ ์ ์งํ๋ ๋ฐ ํ์์ ์ ๋๋ค. ์ผ๋ฐ์ ์ธ ํจ์ ์ ์ดํดํ๊ณ ๋ฌธ์ ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋๋ฒ๊น ํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ๋ฉด ๊ฐ๋ฐ ์๊ฐ์ ํฌ๊ฒ ์ ์ฝํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ขฐ์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
์ฅ์ ๊ณผ ๋จ์
์ฅ์ :
- ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํ ๋ณด์ ๊ฐํ
- ์ฌ์ฉ์ ์ ์ ๊ฐ๋ฅํ ์ธ์ฆ ๋ฉ์ปค๋์ฆ
- ๋ค์ํ ์ธ์ฆ ์ ๊ณต์์์ ํตํฉ
๋จ์ :
- ์ด๋ณด์์๊ฒ๋ ๋์ ํ์ต ๊ณก์
- ๊ตฌ์ฑ ๋ฐ ๋๋ฒ๊น ์ ์ ์ฌ์ ๋ณต์ก์ฑ
Spring Security ๋ก๊ทธ์ธ์ ์ธ์ ์ด๋์ ์ฌ์ฉํ ๊น
Spring Security๋ ์ ์ ์๊ฑฐ๋ ํ๋ซํผ, ์ํ ์์คํ , ์ํฐํ๋ผ์ด์ฆ ์์ค์ ์ ํ๋ฆฌ์ผ์ด์ ๋ฑ ๊ฐ๋ ฅํ ๋ณด์ ์กฐ์น๊ฐ ํ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด์์ ์ ๋๋ค. ์ฌ์ฉ์ ์ธ์ฆ ๋ฐ ๊ถํ ๋ถ์ฌ๊ฐ ํต์ฌ ๊ตฌ์ฑ ์์์ธ ํ๊ฒฝ์์ ๊ฐ์ฅ ์ ํ์ฉ๋ฉ๋๋ค.
Spring Security ๋ก๊ทธ์ธ ๊ตฌํ์ ์ผ๋ฐ์ ์ธ ๋ฌธ์
Spring Security๋ฅผ ๊ตฌํํ๋ฉด์ ๋ก๊ทธ์ธ ํ๋ก์ธ์ค์ ๊ธฐ๋ฅ์ ๋ฐฉํดํ๋ ์ผ๋ฐ์ ์ธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด ์น์ ์์๋ ๋ก๊ทธ์ธ ํ์ด์ง์ UI ๋ถ์ผ์น์ ํผ ์์์ 'name' ์์ฑ ๋๋ฝ์ด๋ผ๋ ๋ ๊ฐ์ง ํํ ๋ฌธ์ ๋ฅผ ๋ค๋ฃน๋๋ค.
UI ๋ฌธ์ : ๋ก๊ทธ์ธ ํ์ด์ง ์์
์ ๋์์ธ๋ ๋ก๊ทธ์ธ ํ์ด์ง๋ ์ฌ์ฉ์ ๊ฒฝํ์ ํ์์ ์ ๋๋ค. ๊ฒฝ์ฐ์ ๋ฐ๋ผ HTML ๊ตฌ์กฐ์ ์์ ์ค์๊ฐ UI ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์ต๋๋ค.
๋ฌธ์ ์๋ณ
๋ฌธ์ : login.html์ ์ถ๊ฐ์ ์ธ ๋ซ๋ div ํ๊ทธ๋ก ์ธํด ๋ก๊ทธ์ธ ๋ฒํผ์ด ์ฌ๋ฐ๋ฅด๊ฒ ํ์๋์ง ์์ต๋๋ค.
ํด๊ฒฐ์ฑ : HTML ๊ตฌ์กฐ๊ฐ ์ ํจํ๋๋ก ์ถ๊ฐ์ ์ธ ๋ซ๋ div๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
1 2 3 4 5 6 7 8 9 |
<!-- Incorrect HTML Structure --> <div class="login-container"> <!-- Login form elements --> </div> <!-- Extra closing div --> <!-- Corrected HTML Structure --> <div class="login-container"> <!-- Login form elements --> </div> |
์ค๋ช : ์ถ๊ฐ์ ์ธ div ํ๊ทธ๋ ๋ ์ด์์์ ๋ฐฉํดํ์ฌ ๋ก๊ทธ์ธ ๋ฒํผ์ด ์๋ชป ์ ๋ ฌ๋๊ฑฐ๋ ๋๋ฝ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ํฉ๋๋ค. ์ ์ ํ HTML ๊ตฌ์กฐ๋ฅผ ๋ณด์ฅํ๋ฉด UI ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ฉ๋๋ค.
๋ฐฑ์๋ ๋ฌธ์ : ํผ ์์์ 'name' ์์ฑ ๋๋ฝ
๋ฐฑ์๋ ๊ธฐ๋ฅ์ ์ฌ์ฉ์ ์ ๋ ฅ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ๋ฐ๋ฅด๊ฒ ์ด๋ฆ์ด ์ง์ ๋ ํผ ์์์ ํฌ๊ฒ ์์กดํฉ๋๋ค.
๋ฌธ์ ์๋ณ
๋ฌธ์ : ๋ก๊ทธ์ธ ํผ์ ์ ๋ ฅ ์์์ name ์์ฑ์ด ๋๋ฝ๋์ด ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ ๋ ฅ ๊ฐ์ ์ฝ์ง ๋ชปํฉ๋๋ค.
ํด๊ฒฐ์ฑ : ๋ฐฑ์๋๊ฐ ํผ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๋งคํํ ์ ์๋๋ก ๊ฐ ์ ๋ ฅ ์์์ name ์์ฑ์ ์ถ๊ฐํฉ๋๋ค.
1 2 3 4 5 |
<!-- Incorrect Form Element --> <input type="email" id="email" /> <!-- Corrected Form Element --> <input type="email" id="email" name="email" /> |
์ค๋ช : name ์์ฑ์ ์๋ฒ๊ฐ ์ ๋ ฅ ๊ฐ์ ์ธ์ํ๊ณ ์ฒ๋ฆฌํ๋ ๋ฐ ์ค์ํฉ๋๋ค. ์์ผ๋ฉด ํผ ๋ฐ์ดํฐ๊ฐ ์๋ฒ ์ธก ๋ณ์์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ฐ์ธ๋ฉ๋์ง ์์ ์ธ์ฆ ๊ณผ์ ์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
Spring Security์์ UserDetailsService ๊ตฌํ
UserDetailsService ์ธํฐํ์ด์ค๋ ์ธ์ฆ ์ค์ ์ฌ์ฉ์ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ๋ Spring Security์ ํต์ฌ ๊ตฌ์ฑ ์์์ ๋๋ค.
UserDetailsService ๊ฐ์
UserDetailsService๋ ์ฌ์ฉ์ ํน์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ ๊ณต๋ ์ฌ์ฉ์ ์ด๋ฆ์ ๊ธฐ์ค์ผ๋ก ์ฌ์ฉ์๋ฅผ ์ฐพ๋ loadUserByUsername ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ๋ฉ์๋๋ Spring Security๊ฐ ์ธ์ฆ ๋ฐ ๊ถํ ๋ถ์ฌ์ ์ฌ์ฉํ๋ UserDetails ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
loadUserByUsername ๋ฉ์๋ ๊ตฌํ
loadUserByUsername ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฒ์ํ๊ณ ์ฌ์ฉ์๋ฅผ ์ฐพ์ ์ ์๋ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค.
๋จ๊ณ๋ณ ๊ตฌํ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
1. <strong>Optional ๋ณ์ ์์ฑ:</strong> Optional<Account> optionalAccount = accountRepository.findOneByEmailIgnoreCase(email); <strong>์ค๋ช
:</strong> ์ฌ์ฉ์๋ฅผ ์ฐพ์ ์ ์์ ๊ฒฝ์ฐ <strong>null</strong> ๊ฐ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด <strong>Optional</strong>์ด ์ฌ์ฉ๋ฉ๋๋ค. 2. <strong>๊ณ์ ์กด์ฌ ์ฌ๋ถ ํ์ธ:</strong> if (!optionalAccount.isPresent()) { throw new UserNotFoundException("Account not found"); } <strong>์ค๋ช
:</strong> ๊ณ์ ์ด ์กด์ฌํ์ง ์์ผ๋ฉด ์ธ์ฆ์ ์งํํ ์ ์์์ ๋ํ๋ด๊ธฐ ์ํด <strong>UserNotFoundException</strong>์ด ๋ฐ์ํฉ๋๋ค. 3. <strong>๊ณ์ ์ธ๋ถ ์ ๋ณด ๊ฒ์:</strong> Account account = optionalAccount.get(); <strong>์ค๋ช
:</strong> ์ถ๊ฐ ์ฒ๋ฆฌ๋ฅผ ์ํด <strong>Optional</strong>์์ <strong>Account</strong> ๊ฐ์ฒด๋ฅผ ์ถ์ถํฉ๋๋ค. 4. <strong>UserDetails ๊ฐ์ฒด ๋ฐํ:</strong> return new User(account.getEmail(), account.getPassword(), authorities); <strong>์ค๋ช
:</strong> <strong>User</strong> ๊ฐ์ฒด๋ <strong>UserDetails</strong>๋ฅผ ๊ตฌํํ๋ฉฐ, ์ฌ์ฉ์ ์ด๋ฆ, ๋น๋ฐ๋ฒํธ, ๊ถํ ๋ฑ์ ํ์ํ ์ ๋ณด๋ฅผ ์ธ์ฆ์ ์ ๊ณตํฉ๋๋ค. |
์ ์ฒด ๋ฉ์๋ ๊ตฌํ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { Optional<Account> optionalAccount = accountRepository.findOneByEmailIgnoreCase(email); if (!optionalAccount.isPresent()) { throw new UsernameNotFoundException("Account not found"); } Account account = optionalAccount.get(); return new User(account.getEmail(), account.getPassword(), getAuthorities()); } private Collection<? extends GrantedAuthority> getAuthorities() { List<SimpleGrantedAuthority> authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority("ROLE_USER")); return authorities; } |
์ค๋ช : loadUserByUsername ๋ฉ์๋๋ ๋ฆฌํฌ์งํ ๋ฆฌ์์ ์ฌ์ฉ์ ๊ณ์ ์ ๊ฒ์ํ๊ณ , ์กด์ฌ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ฉฐ, ์ฌ์ฉ์์ ์ด๋ฉ์ผ, ๋น๋ฐ๋ฒํธ, ๊ถํ์ ๊ฐ์ง UserDetails ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
Spring Security์์ ๋ถ์ฌ๋ ๊ถํ ๋ฐ ์ญํ ์ฒ๋ฆฌ
๋ถ์ฌ๋ ๊ถํ๊ณผ ์ญํ ์ ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ ์ฌ์ฉ์ ๊ถํ์ ์ ์ํ๋ ๋ฐ ๊ธฐ๋ณธ์ ์ ๋๋ค. ์ ์ ํ ๊ตฌ์ฑ์ ์ฌ์ฉ์์๊ฒ ์ ์ ํ ์ก์ธ์ค ์์ค์ ๋ณด์ฅํฉ๋๋ค.
๋ถ์ฌ๋ ๊ถํ ์ดํด
- Granted Authority: ๊ถํ ๋๋ ๊ถ๋ฆฌ๋ฅผ ๋ํ๋ ๋๋ค. ์ฌ์ฉ์์๊ฒ ์ํํ ์ ์๋ ์์ ์ ๊ฒฐ์ ํ๋ ๊ถํ ๋ถ์ฌ์ ํต์ฌ ๊ฐ๋ ์ ๋๋ค.
- ์ญํ vs. ๊ถํ: ์ผ๋ฐ์ ์ผ๋ก ์ญํ ์ ๊ถํ์ ๊ทธ๋ฃน์ ๋๋ค. ์๋ฅผ ๋ค์ด, ROLE_ADMIN์ ์ฌ๋ฌ ํน์ ๊ถํ์ ํฌํจํ ์ ์์ต๋๋ค.
๋ถ์ฌ๋ ๊ถํ ๊ตฌ์ฑ
์ ํํ ๊ถํ ๊ด๋ฆฌ๋ฅผ ์ํด ๋ถ์ฌ๋ ๊ถํ์ ์ ์ ํ๊ฒ ๊ตฌ์ฑํ๋ ๊ฒ์ด ํ์์ ์ ๋๋ค.
๋จ๊ณ๋ณ ๊ตฌ์ฑ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
1. <strong>๊ถํ ๋ชฉ๋ก ์์ฑ:</strong> List<GrantedAuthority> authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority("ROLE_USER")); <strong>์ค๋ช
:</strong> ๋ถ์ฌ๋ ๊ถํ์ ๋ชฉ๋ก์ ๋ง๋ค๊ณ ์ฌ์ฉ์์๊ฒ ํ ๋น๋ ํน์ ์ญํ ๋๋ ๊ถํ์ผ๋ก ์ฑ์๋๋ค. 2. <strong>UserDetails ๊ตฌํ ์
๋ฐ์ดํธ:</strong> return new User(account.getEmail(), account.getPassword(), authorities); <strong>์ค๋ช
:</strong> <strong>User</strong> ๊ฐ์ฒด๋ ์ฌ์ฉ์์ ์ด๋ฉ์ผ, ๋น๋ฐ๋ฒํธ, ๋ถ์ฌ๋ ๊ถํ ๋ชฉ๋ก๊ณผ ํจ๊ป ์ธ์คํด์คํ๋ฉ๋๋ค. 3. <strong>๊ถํ ๋๋ฝ ์ฒ๋ฆฌ:</strong> if (authorities.isEmpty()) { throw new UsernameNotFoundException("No authorities granted"); } <strong>์ค๋ช
:</strong> ์ฌ์ฉ์๊ฐ ๋ถ์ฌ๋ ๊ถํ ์์ด ์ธ์ฆ๋์ง ์๋๋ก ํ์ฌ ๋ณด์ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํฉ๋๋ค. |
UserDetailsService์์์ ์์ ๊ตฌ์ฑ
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { Optional<Account> optionalAccount = accountRepository.findOneByEmailIgnoreCase(email); if (!optionalAccount.isPresent()) { throw new UsernameNotFoundException("Account not found"); } Account account = optionalAccount.get(); List<GrantedAuthority> authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority("ROLE_USER")); return new User(account.getEmail(), account.getPassword(), authorities); } |
์ค๋ช : ์ด ๋ฉ์๋๋ ์ธ์ฆ๋ ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ROLE_USER ๊ถํ์ด ํ ๋น๋๋๋ก ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ํ์ฅํ ์ ์์ต๋๋ค.
Spring Security ๋ก๊ทธ์ธ ์ค๋ฅ ๋๋ฒ๊น
๋๋ฒ๊น ์ Spring Security ๊ตฌํ ์ค ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ํ์์ ์ธ ๊ธฐ์ ์ ๋๋ค. ์ด ์น์ ์์๋ ์ผ๋ฐ์ ์ธ ์ค๋ฅ์ ํจ๊ณผ์ ์ธ ๋๋ฒ๊น ๊ธฐ๋ฒ์ ํ๊ตฌํฉ๋๋ค.
์ผ๋ฐ์ ์ธ ์ค๋ฅ ๋ฐ ์์ธ
- Cannot Pass a Null Granted Authority Collection
์์ธ: UserDetails ๊ฐ์ฒด ์์ฑ ์ ๋ถ์ฌ๋ ๊ถํ ์ปฌ๋ ์ ์ null ๊ฐ์ ์ ๋ฌํ๋ ค๋ ์๋.
ํด๊ฒฐ์ฑ : ๋ถ์ฌ๋ ๊ถํ ์ปฌ๋ ์ ์ด ์ด๊ธฐํ๋๊ณ null์ด ์๋๋๋ก ํฉ๋๋ค.
12List<GrantedAuthority> authorities = new ArrayList<>();authorities.add(new SimpleGrantedAuthority("ROLE_USER")); - User Not Found Exception
์์ธ: ์ฌ์ฉ์๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์กด์ฌํ์ง ์์ ๋ ์ ํ๋ฆฌ์ผ์ด์ ์์ UsernameNotFoundException์ ๋์ง.
ํด๊ฒฐ์ฑ : ์ฌ์ฉ์๊ฐ ์กด์ฌํ๋์ง ํ์ธํ๊ณ ๋ก๊ทธ์ธ ์ค์ ์ด๋ฉ์ผ ์ฃผ์๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ ฅ๋์๋์ง ๊ฒ์ฆํฉ๋๋ค.
- Breakpoint Not Initialized
์์ธ: ๋๋ฒ๊ฑฐ๊ฐ ์๋ํ ์ค๋จ์ ์ ๋๋ฌํ์ง ๋ชปํด ์ฝ๋ ๊ฒฝ๋ก๊ฐ ์คํ๋์ง ์๊ฑฐ๋ ์ค๋จ์ ์ด ์ ๋๋ก ์ค์ ๋์ง ์์ ๊ฒฝ์ฐ๊ฐ ๋ง์.
ํด๊ฒฐ์ฑ : ์ค๋จ์ ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋ฐฐ์น๋์๋์ง ๊ทธ๋ฆฌ๊ณ ๊ด๋ จ ์ฝ๋๊ฐ ์คํ๋๊ณ ์๋์ง ํ์ธํฉ๋๋ค.
Spring Boot์์์ ๋๋ฒ๊น ๊ธฐ์
ํจ๊ณผ์ ์ธ ๋๋ฒ๊น ์ ๋ต์ ๋ฌธ์ ๋ฅผ ์ ์ํ๊ฒ ์๋ณํ๊ณ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
์ค๋จ์ ์ฌ์ฉ
- ์ค๋จ์ ์ค์ : loadUserByUsername ๋ฉ์๋ ์์๊ณผ ๊ฐ์ ์ฝ๋์ ์ค์ํ ์ง์ ์ ์ค๋จ์ ์ ๋ฐฐ์นํฉ๋๋ค.
- ๋๋ฒ๊ทธ ๋ชจ๋๋ก ์คํ: ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ฒ๊ทธ ๋ชจ๋๋ก ์์ํ์ฌ ์คํ ํ๋ฆ์ ๋ชจ๋ํฐ๋งํ๊ณ ๋ณ์ ์ํ๋ฅผ ๊ฒ์ฌํฉ๋๋ค.
- ๋ณ์ ๊ฒ์ฌ: ๋๋ฒ๊ฑฐ๋ฅผ ์ฌ์ฉํ์ฌ optionalAccount ๋ฐ authorities์ ๊ฐ์ ๋ณ์์ ๊ฐ์ ๊ฒ์ฌํฉ๋๋ค.
๋ก๊น
- ์์ธ ๋ก๊น
ํ์ฑํ: application.properties์์ ๋ก๊น
์์ค์ ๊ตฌ์ฑํ์ฌ ์์ธ ์ ๋ณด๋ฅผ ์บก์ฒํฉ๋๋ค.
1logging.level.org.springframework.security=DEBUG - ๋ก๊ทธ ๋ฌธ ์ถ๊ฐ: ๋ก๊น
ํ๋ฆ๊ณผ ๋ฐ์ดํฐ ๊ฐ์ ์ถ์ ํ๊ธฐ ์ํด ๋ก๊ทธ ๋ฌธ์ ์ฝ์
ํฉ๋๋ค.
1logger.debug("Attempting to load user with email: " + email);
์คํ ์ถ์ ๊ฒํ
- ์ค๋ฅ ๋ถ์: ์์ธ์ ์์ธ์ ์๋ณํ๊ธฐ ์ํด ์คํ ์ถ์ ์ ์ฃผ์ ๊น๊ฒ ์ฝ์ต๋๋ค.
- ํ๋ฆ ์ถ์ : ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ฝ๋ ์ง์ ๊น์ง ์คํ ์ถ์ ์ ๋ฐ๋ผ๊ฐ๋๋ค.
๋ก๊ทธ์ธ ๊ธฐ๋ฅ ํ ์คํธ
Spring Security๋ฅผ ๊ตฌํํ๊ณ ๊ตฌ์ฑํ ํ, ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ด ์์๋๋ก ์๋ํ๋์ง ์ฒ ์ ํ ํ ์คํธํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๋๋ฒ๊ทธ ๋ชจ๋์์ ์ ํ๋ฆฌ์ผ์ด์ ์คํ
๋๋ฒ๊ทธ ๋ชจ๋์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ๋ฉด ์คํ ํ๋ฆ์ ๋ชจ๋ํฐ๋งํ๊ณ ์ค์๊ฐ์ผ๋ก ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ ์ ์์ต๋๋ค.
๋๋ฒ๊ทธ ๋ชจ๋๋ก ์คํํ๋ ๋จ๊ณ
- ์ค๋จ์ ์ค์ : loadUserByUsername ๋ฉ์๋ ๋ด์ ๊ฐ์ ์ ๋ต์ ์ธ ์ง์ ์ ์ค๋จ์ ์ ๋ฐฐ์นํฉ๋๋ค.
- ๋๋ฒ๊ฑฐ ์์: IDE์ ๋๋ฒ๊ฑฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ฒ๊ทธ ๋ชจ๋๋ก ์คํํฉ๋๋ค.
- ์คํ ๋ชจ๋ํฐ๋ง: ๋ก๊ทธ์ธ ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฉ์์ ๊ด์ฐฐํฉ๋๋ค.
์์ :
1 2 3 4 5 6 7 8 |
public class AccountService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { // ์ฌ๊ธฐ์ ์ค๋จ์ ์ค์ Optional<Account> optionalAccount = accountRepository.findOneByEmailIgnoreCase(email); // ์ถ๊ฐ ์ฝ๋... } } |
์ค๋ช : loadUserByUsername ๋ฉ์๋ ๋ด์ ์ค๋จ์ ์ ์ค์ ํจ์ผ๋ก์จ ์คํ ์ค์ optionalAccount ๋ฐ ๊ธฐํ ๋ณ์์ ์ํ๋ฅผ ๊ฒ์ฌํ ์ ์์ต๋๋ค.
์ฑ๊ณต์ ์ธ ๋ก๊ทธ์ธ ํ์ธ
๋๋ฒ๊น ์ ๋ง์น๊ณ ์ค๋ฅ๊ฐ ์์์ ํ์ธํ ํ, ๋ง์ง๋ง ๋จ๊ณ๋ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ด ์๋๋๋ก ์๋ํ๋์ง ํ์ธํ๋ ๊ฒ์ ๋๋ค.
๊ฒ์ฆ ๋จ๊ณ
- ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋: ์น ๋ธ๋ผ์ฐ์ ์์ http://localhost:8080/login์ ์ ๊ทผํฉ๋๋ค.
- ์๊ฒฉ ์ฆ๋ช ์ ๋ ฅ: ์ ํจํ ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ ์กฐํฉ์ ์ ๋ ฅํฉ๋๋ค (์: account01@studyeasy.org ๋ฐ password).
- ํผ ์ ์ถ: ๋ก๊ทธ์ธ ๋ฒํผ์ ํด๋ฆญํ์ฌ ์ธ์ฆ์ ์๋ํฉ๋๋ค.
- ๋ฆฌ๋๋ ์ ํ์ธ: ์ฑ๊ณต์ ์ธ ๋ก๊ทธ์ธ์ด ํํ์ด์ง๋ ์๋ํ ๋๋ฉ ํ์ด์ง๋ก ๋ฆฌ๋๋ ์ ๋๋์ง ํ์ธํฉ๋๋ค.
์์ ์ํฌํ๋ก์ฐ:
- ๋ก๊ทธ์ธ ํ์ด์ง ์ ๊ทผ:
- ์๊ฒฉ ์ฆ๋ช
์
๋ ฅ:
- ์ด๋ฉ์ผ: account01@studyeasy.org
- ๋น๋ฐ๋ฒํธ: password
- ๋ก๊ทธ์ธ ํด๋ฆญ:
- ์ฑ๊ณต์ ์ธ ๋ฆฌ๋๋ ์
:
์ค๋ช : ์ ํจํ ์๊ฒฉ ์ฆ๋ช ์ ์ ๋ ฅํ๊ณ ํผ์ ์ ์ถํ๋ฉด, ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉ์๋ฅผ ์ธ์ฆํ๊ณ ํํ์ด์ง๋ก ๋ฆฌ๋๋ ์ ํ์ฌ ๋ก๊ทธ์ธ ํ๋ก์ธ์ค๊ฐ ์ ๋๋ก ์๋ํจ์ ํ์ธํด์ผ ํฉ๋๋ค.
๊ฒฐ๋ก ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก
Spring Security ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ๋๋ฒ๊น ํ๋ ค๋ฉด ํ๋ ์์ํฌ์ ์ผ๋ฐ์ ์ธ ๋ณด์ ์์น์ ๋ชจ๋ ์ข ํฉ์ ์ผ๋ก ์ดํดํด์ผ ํฉ๋๋ค. ์ผ๋ฐ์ ์ธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ , ์ฌ์ฉ์ ์ธ๋ถ ์ ๋ณด์ ๊ถํ์ ์ ์ ํ๊ฒ ๊ตฌ์ฑํ๋ฉฐ, ํจ๊ณผ์ ์ธ ๋๋ฒ๊น ๊ธฐ๋ฒ์ ํ์ฉํจ์ผ๋ก์จ ๊ฐ๋ฐ์๋ ์์ ํ๊ณ ํจ์จ์ ์ธ ์ธ์ฆ ์์คํ ์ ๋ณด์ฅํ ์ ์์ต๋๋ค.
์ฃผ์ ์ฌํญ
- ์ธ๋ถ ์ฌํญ์ ์ฃผ์: HTML ๊ตฌ์กฐ์ ์์ ์ค์๋ ํผ ์์ฑ ๋๋ฝ์ ์ ์ฒด ๋ก๊ทธ์ธ ํ๋ก์ธ์ค๋ฅผ ๋ฐฉํดํ ์ ์์ต๋๋ค.
- UserDetailsService์ ์ ์ ํ ๊ตฌํ: ์ธ์ฆ ์ค ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๊ฒ์ํ๊ณ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค.
- ๋ถ์ฌ๋ ๊ถํ ์ฒ๋ฆฌ: ์ ์ ํ ์ญํ ๊ณผ ๊ถํ์ ํ ๋นํ๋ ๊ฒ์ ํจ๊ณผ์ ์ธ ๊ถํ ๋ถ์ฌ๋ฅผ ์ํด ์ค์ํฉ๋๋ค.
- ํจ๊ณผ์ ์ธ ๋๋ฒ๊น : ์ค๋จ์ , ๋ก๊น ๋ฐ ์คํ ์ถ์ ๋ถ์์ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ์ ์ํ๊ฒ ํด๊ฒฐํฉ๋๋ค.
- ์ฒ ์ ํ ํ ์คํธ: ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ฒ์ฆํ์ฌ ์ ๋ขฐ์ฑ์ ๋ณด์ฅํ๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํต๋๋ค.
๋ชจ๋ฒ ์ฌ๋ก
- ์ผ๊ด๋ ๋ช ๋ช ๊ท์น: ํผ ์์์ ๋ํ ๋ช ํํ๊ณ ์ผ๊ด๋ ์ด๋ฆ์ ์ฌ์ฉํ์ฌ ๋งคํ ๋ฌธ์ ๋ฅผ ํผํฉ๋๋ค.
- ์์ ํ ๋น๋ฐ๋ฒํธ ์ฒ๋ฆฌ: ํญ์ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ๋น๋ฐ๋ฒํธ๋ฅผ ์์ ํ๊ฒ ์ ์ฅํฉ๋๋ค.
- ์ ๊ธฐ์ ์ธ ์ ๋ฐ์ดํธ: ์ต์ ๋ณด์ ๊ธฐ๋ฅ๊ณผ ์์ ์ ๋ฐ์ํ๊ธฐ ์ํด Spring Security ๋ฐ ๊ด๋ จ ์ข ์์ฑ์ ์ต์ ์ํ๋ก ์ ์งํฉ๋๋ค.
- ์ข ํฉ์ ์ธ ๋ก๊น : ๋๋ฒ๊น ๋ฐ ๋ชจ๋ํฐ๋ง์ ์ฉ์ดํ๊ฒ ํ๊ธฐ ์ํด ์์ธํ ๋ก๊น ์ ๊ตฌํํฉ๋๋ค.
- ์ฌ์ฉ์ ํผ๋๋ฐฑ: ๋ก๊ทธ์ธ ์คํจ ์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ๋ ธ์ถํ์ง ์์ผ๋ฉด์ ์ฌ์ฉ์์๊ฒ ๋ช ํํ๊ณ ์ ์ตํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๊ณตํฉ๋๋ค.
SEO ํค์๋: Spring Security ๋ก๊ทธ์ธ, Spring Boot ์ธ์ฆ, UserDetailsService ๊ตฌํ, Spring Security ๋๋ฒ๊น , Granted Authorities Spring, Spring Security ์ญํ , ๋ก๊ทธ์ธ ๋ฌธ์ ์์ Spring, Spring Security ๋ชจ๋ฒ ์ฌ๋ก, Java ์น ๋ณด์, Spring Security ํํ ๋ฆฌ์ผ
์ฐธ๊ณ : ์ด ๊ธฐ์ฌ๋ AI์ ์ํด ์์ฑ๋์์ต๋๋ค.