๐ค์คํ๋ง ์ํ๋ฆฌํฐ ๊ตฌํํ๊ธฐ
- ์คํ๋ง ์ํ๋ฆฌํฐ๋ ์คํ๋ง ๊ธฐ๋ฐ์ ์ ํ๋ฆฌ์ผ์ด์ (์ธ์ฆ, ๊ถํ, ์ธ๊ฐ ๋ฑ)์ ๋ด๋นํ๋ ์คํ๋ง ํ์ ํ๋ ์์ํฌ์.
1. ์ธ์ฆ์ด ์ ๋ ์ฌ์ฉ์๋ค์ด ์ถ์ ํ ์ ์๋ /auth/ ๊ฒฝ๋ก๋ฅผ UserController์ ์ถ๊ฐํด ์ค๋ค.
2. ์์ฒญ์ด ๋ค์ด์์ ๋ ์ธ์ฆ์ด ํ์ํ์ง, ํ์ํ์ง ์์์ง ๊ตฌ๋ถํ๋ ์ํ๋ฆฌํฐ ํํฐ๋ฅผ ๋ฑ๋กํ๋ SecurityConfig ํด๋์ค ์์ฑ
3. ์ค์ ํ localhost:8080 ์ฃผ์๋ก ์ ๊ทผํ๋ฉด ์๋์ ๊ฐ์ ํ๋ฉด์ด ๋จ์ง๋ง
4. ์ธ์ฆ์์ด ์ ๊ทผํ ์ ์๋๋ก ์ค์ ํด๋์ /auth/ ์ฃผ์๋ก ์ ์ํ๋ฉด ํ์ด์ง๊ฐ ์ ๋จ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
5. ๊ธฐ์กด์ ์์ฑํ loginForm.jsp์์ formํ๊ทธ๋ฅผ ์์ ํ๋ค.
<form action="/auth/loginProc" method="post">
6.SecurityConfig ์ฝ๋๋ฅผ ์๋์ ๊ฐ์ด ์์ ํ๋ฉด ์์ formํ๊ทธ์ ๊ฑธ์ด๋์ /auth/loginProc ์ฃผ์๋ฅผ UserApiController์ ๋ฐ๋ก ๋งคํํด์ค ํ์๊ฐ ์๋ค.
๐ค๋น๋ฐ๋ฒํธ ํด์ฌ(์ํธํ) ๊ตฌํํ๊ธฐ
1. ์ํ๋ฆฌํฐ๊ฐ ๊ฐ๊ณ ์๋ ํจ์ ์ฌ์ฉ
2. JUnit ํ ์คํธ ์ฝ๋ ์์ฑ
์๋์ ๊ฐ์ด ์ํธํ๊ฐ ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
3. UserService์ ์ํธํ ์ฝ๋ ์์ฑ
4. DB๋ฅผ ์ด๊ธฐํํ๊ณ ๋ค์ ํ์๊ฐ์ ์ ํด๋ณด๋ฉด ํด์ฌํ๋ ๋น๋ฐ๋ฒํธ๊ฐ ์ ๋ค์ด๊ฐ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๐กXSS & CSRF ์ฐจ์ด์
- ์น์ฌ์ดํธ ์ทจ์ฝ์ ๊ณต๊ฒฉ์ ํ๋๋ก ์ฌ์ฉ์๊ฐ ์์ ์ ์์ง์๋ ๋ฌด๊ดํ๊ฒ ๊ณต๊ฒฉ์๊ฐ ์๋ํ ํ์(์์ , ์ญ์ ๋ฑ)๋ฅผ ํน์ ์น์ฌ์ดํธ์ ์์ฒญํ๊ฒ ํ๋ ๊ณต๊ฒฉ.
- XSS๋ฅผ ์ด์ฉํ ๊ณต๊ฒฉ์ ์ฌ์ฉ์๊ฐ ํน์ ์น์ฌ์ดํธ๋ฅผ ์ ์ฉํ๋ ์ ์ ๋ ธ๋ฆฐ ๊ฒ.
- CSRF๋ ํน์ ์น์ฌ์ดํธ๊ฐ ์ฌ์ฉ์์ ์น ๋ธ๋ผ์ฐ์ ๋ฅผ ์ ์ฉํ๋ ์ํ๋ฅผ ๋ ธ๋ฆฐ ๊ฒ.
- ๋์ ๋ฐฉ์ : CSRF ํ ํฐ ์ฌ์ฉ, ์ฌ์ฉ์์ ์ํธ ์ฒ๋ฆฌ ๊ธฐ๋ฅ ์ ์ฉ, ์ฌ์ธ์ฆ ์๊ตฌ
- XSS๋ ๊ณต๊ฒฉ ๋์์ด ํด๋ผ์ด์ธํธ, CSRF๋ ์๋ฒ์ด๋ค.


๐ค์คํ๋ง ์ํ๋ฆฌํฐ ๋ก๊ทธ์ธ ๊ตฌํํ๊ธฐ
1. PrincipalDetail ์์ฑ
- ๋ก๊ทธ์ธํผ์์ ์๋ฃ ๋ฒํผ์ ๋๋ฅด๋ฉด form submit์ผ๋ก username, password๋ฅผ ๋๊ฒจ์ค๋ค.
- SecurityConfig ํด๋์ค์์ ๋ก๊ทธ์ธ ๊ฐ๋ก์ฑ๊ณ ์งํํจ.
- ์คํ๋ง์ํ๋ฆฌํฐ๊ฐ ๋ก๊ทธ์ธ ์์ฒญ์ ๊ฐ๋ก์ฑ์ ๋ก๊ทธ์ธ ์งํํ๊ณ ์๋ฃ๊ฐ ๋๋ฉด UserDetails ํ์ ์ ์ค๋ธ์ ํธ(PrincipalDetail)๋ฅผ ์คํ๋ง ์ํ๋ฆฌํฐ์ ๊ณ ์ ํ ์ธ์ ์ ์ฅ์์ ์ ์ฅํด์ค๋ค.
@Getter
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 : ๋ง๋ฃ ์๋จ / false : ๋ง๋ฃ๋จ)
@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();
//collectors.add(new GrantedAuthority() {
//@Override
//public String getAuthority() {
//์คํ๋ง์์ ROLE์ ๋ฐ์ ๋ ๊ท์น์. ROLE_ ๊ผญ ๋ฃ์ด์ค์ผํจ.
//return "ROLE_"+user.getRole();
//}
//});
collectors.add(()->{return "ROLE_"+user.getRole();});
return collectors;
}
}
2. PrincipalDetailService ์์ฑ
- ์คํ๋ง์ด ๋ก๊ทธ์ธ ์์ฒญ์ ๊ฐ๋ก์ฑ ๋ username, password ๋ณ์ 2๊ฐ๋ฅผ ๊ฐ๋ก์ฑ๋๋ฐ password๋ถ๋ถ ์ฒ๋ฆฌ๋ ์์์ํจ.
- username์ด DB์ ์๋์ง๋ง ํ์ธํด์ returnํด์ฃผ๋ฉด ๋จ.
3. username ์ฐพ๋ ๋ฉ์๋ UserRepository์ ์์ฑ
//SELECT * FROM user WHERE username = ?
Optional<User> findByUsername(String username);
๐ก๋ค์ ์ ๋ฆฌ
- ๋ก๊ทธ์ธ ์์ฒญ์ด ์ค๋ ์๊ฐ '/auth/loginProc' ์ฃผ์๋ฅผ SecurityConfig๊ฐ ๊ฐ๋ก์ฑ.
- ๊ทธ ๋ค์ PrincipalDetailService๊ฐ ๊ฐ๊ณ ์๋ ๋ฉ์๋์์ username์ด ์๋์ง ๋น๊ต ํ new PrincipalDetail(principal)๋ฅผ ๋ฆฌํดํจ.
- ๋ฆฌํดํ ๋ ์๋ ์ฝ๋๋ฅผ ํตํด ์ฌ์ฉ์๊ฐ ์ ์ ๋น๋ฐ๋ฒํธ์ DB๋ฅผ ๋น๊ตํด์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ํธํํ๋ค.
- ๋น๊ต๊ฐ ๋๋๋ฉด principal ๊ฐ์ฒด์ ์ ์ฅ์ด ๋จ.
4. ๋ก๊ทธ์ธ์ด ์ ๋๋ค.


'Springboot > Springboot Blog Project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๊ธ ์์ธ๋ณด๊ธฐ, ๊ธ ์ญ์ ํ๊ธฐ, ๊ธ ์์ ํ๊ธฐ ๊ตฌํํ๊ธฐ (1) | 2022.09.25 |
---|---|
๊ธ์ฐ๊ธฐ, ๊ธ ๋ชฉ๋ก๋ณด๊ธฐ, ํ์ด์ง ๊ตฌํํ๊ธฐ (0) | 2022.09.25 |
๋ธ๋ก๊ทธ ํ๋ก์ ํธ ์ ํต์ ์ธ ๋ฐฉ์์ ๋ก๊ทธ์ธ ๋ฐฉ๋ฒ (0) | 2022.09.24 |
ํธ๋์ญ์ , DB๊ฒฉ๋ฆฌ์์ค-๋ฉํ์ฝ๋ฉ (0) | 2022.09.24 |
Service๊ฐ ํ์ํ ์ด์ - ๋ฉํ ์ฝ๋ฉ ์ฐธ์กฐ- ์์ ์ค (0) | 2022.09.24 |