ํฐ์คํ ๋ฆฌ ๋ทฐ
[Spring Security] ํ ํฐ ๋ฐํ ํ API์ ํ ํฐ ์ธ์ฆ ์ ์ฐจ ์ถ๊ฐํ๊ธฐ
Nickolodeon 2022. 12. 6. 23:57๐ก Introduction
์ด๋ฒ ํฌ์คํธ์์๋ ์คํ๋ง ๋ถํธ ํต์ฌ ๊ฐ์ด๋ ์ฑ ์์ ๋์จ Spring Security ๋ฅผ ์ฌ์ฉํด ํ ํฐ ์ธ์ฆ์ ๊ตฌํํ๋ ๊ณผ์ ์ ๋ด๊ฐ ๊ตฌํํ ์์์ ๋ฐ๋ผ ์ค๋ช ํด๋ณธ๋ค.
๐งพ ๋จ๊ณ๋ณ๋ก ํด๋์ค ์์ฑํ๊ธฐ
๋จผ์ , ์ปจํธ๋กค๋ฌ๋ฅผ ์์ฑํ๋ค.
์ปจํธ๋กค๋ฌ๋ ์๋์ ๊ฐ์ด ํ ํฐ์ ์์ฑํด์ ํ ํฐ์ ๋ฐํํ๋ค.
๋นจ๊ฐ์์ผ๋ก ๋์จ JwtTokenProvider ๋ฅผ ์์ฑํด์ฃผ์. ๊ทธ๋ฆฌ๊ณ ๋ด๋ถ์ createToken() ๋ฉ์๋ ๊ตฌํ ์ ์, ํ์ํ ์์กด์ฑ์ด ์๋ค:
์ด์ ์ค๋น๊ฐ ๋์์ผ๋, JwtTokenProvider ๋ฅผ ๊ตฌํํด๋ณธ๋ค.
ํด๋์ค ์์ฑ ํ, JSON Web Token ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ ๋ค์ํ ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ ํ ํฐ์ ๋ฐ๊ธํ๋ ๊ธฐ๋ฅ์ createToken() ๋ฉ์๋์์ ๊ตฌํํ๋ค:
์ด ์ ๋ ์์ ์์ ์ฐ์ ์ดํ๋ฆฌ์ผ์ด์ ์ ์คํํด ๋ณด์๋ค. Swagger ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์๋ ํ ์คํธ ํ๊ธฐ์ ํธ๋ฆฌํ ๊ฒ ๊ฐ์ ์ถ๊ฐํด์ฃผ๊ธฐ๋ก ํ๋ค. springfox-boot-starter ์ springfox-swagger-ui ๋ฅผ ์์กด์ฑ์ ์ถ๊ฐํด์ฃผ์๋ค. ๋ค์ ๋ ์ค์ด๋ค:
implementation 'io.springfox:springfox-swagger-ui:3.0.0'
implementation 'io.springfox:springfox-boot-starter:3.0.0'
๊ทธ๋ฆฌ๊ณ configuration ํจํค์ง์ SwaggerConfig ํด๋์ค๋ฅผ ์ถ๊ฐํ๋ค:
Swagger ๋ฅผ ์คํํ๊ธฐ ์ , Spring Security ์์ ์ธ์ฆ๊ณผ ์ธ๊ฐ ๊ธฐ๋ฅ์ ๊ตฌํํ ๋ ์ฌ์ฉํ๋ ๋ณด์ ํํฐ๋ฅผ ๋จผ์ ์์ฐ๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ด SecurityConfig ํด๋์ค๋ฅผ ์์ฑํด์ฃผ์๋ค:
์ดํ localhost:8080/swagger-ui/ ๋ก ์ ์ํ์ ๋์ ๋ชจ์ต์ด๋ค:
์ด๋ ๊ฒ ๋ณด์ํํฐ๊ฐ ๋ํดํธ๋ก ์ธ์ฆ์ ์ํํ ๋ ์ฌ์ฉํ๋ ํํฐ์ธ UsernamePasswordAuthenticationFilter ๋ ์ธ์ฆ์ด ๋์ง ์์ ์ํ์์๋ ๋ก๊ทธ์ธ ํผ์ ํ๋ฉด์ ๋์ด๋ค. ์ด์ , ๋ณด์ ํํฐ์ ๋ช ๊ฐ์ง ์์ฑ๋ค์ ์ค์ ํด์ ์คํ๋ง ์ํ๋ฆฌํฐ์ ๋์์ ์ฌ๊ตฌ์ฑํด๋ณด์.
๐ ๋ณด์ ํํฐ ๊ตฌํํ๊ธฐ
์ฐ์ , ๋ณด์ ํํฐ์ ๊ตฌํ์ SecurityConfig ํด๋์ค์ securityFitlerChain() ๋ฉ์๋๋ฅผ ํตํด ์ด๋ค์ง๋ค:
์์ฒญ๊ณผ DispatcherServlet ์ฌ์ด์ ํํฐ๊ฐ ์ด๋ป๊ฒ ๋์ํ๋์ง๋ฅผ ์ค์ ํด์ค ๊ฒ์ด๋ค. ์ด์ , ๋ค์ Swagger ๋ฅผ ์คํํด๋ณด์. ์๋ง ์๋ฌด๊ฒ๋ ๋์ค์ง ์์ ๊ฒ์ด๋ค. addFilterBefore() ๋ฉ์๋๊ฐ ์ค์ ํด์ค ์์ฑ์ด Jwt ํ ํฐ ํํฐ๋ฅผ ๋จผ์ ์คํํ๋ค๋ ์๋ฏธ๋ฅผ ๊ฐ๊ณ ์๊ณ , ์์ง Jwt ํ ํฐ ํํฐ๋ฅผ ๊ตฌํํ์ง ์์๊ธฐ ๋๋ฌธ์ ์๋ฌด๊ฒ๋ ๋ณด์ด์ง ์๋ ๊ฒ์ด๋ค. ์ด์ , ํ ํฐ ํํฐ๋ฅผ ๊ตฌํํด๋ณผ ์ฐจ๋ก์ด๋ค.
๐ ํ ํฐ ํํฐ ๊ตฌํํ๊ธฐ
ํ ํฐ ํํฐ์ ์ญํ ์ ํ ํฐ์ด ์กด์ฌํ๋์ง ์ฌ๋ถ์ ์ ํจํ์ง์ ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ ํ, ๊ฒ์ฌ์์ ํต๊ณผํ๋ฉด SecurityContextHolder ์ ์ธ์ฆ๋ ํ ํฐ์ ์ ์ฅํ๋ ๊ฒ์ด๋ค. ์ ์ฅ๋ ์ดํ์๋ ์ธ์ฆ๋ ํ ํฐ์ ๊ฐ์ง ์ฌ์ฉ์๋ผ๋ ๊ฒ์ด ํ์ธ๋๊ธฐ ๋๋ฌธ์ ์ธ์ฆ์ด ์๋ฃ๋๋ ๊ฒ์ด๋ค.
๋จผ์ , ํ ํฐ ํํฐ๋ฅผ ๊ตฌํํ JwtAuthenticationFilter ํด๋์ค๋ฅผ ์์ฑํด์ค๋ค:
์ค๋ฒ๋ผ์ด๋ฉ๋ doFilterInternal() ๊ฐ ๋ฐ๋ก ํํฐ ๋ด์์ ํ ํฐ์ด ์กด์ฌํ๋์ง, ํ๋ค๋ฉด ์ ํจํ์ง ํ์ธํ๊ณ ์ฌ์ฉ์๋ฅผ ์ธ์ฆํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๋ฉ์๋์ด๋ค. ๊ธฐ๋ฅ ํ๋์ฉ ๊ตฌํํด๋ณด๊ฒ ๋ค. ๊ทผ๋ฐ ๊ธฐ๋ฅ์ ๋ชจ๋ ๋ฉ์๋ ๋ด๋ถ์์ ๊ตฌํํด๋ ๋์ง๋ง ์ธ๋ถ ๋ฉ์๋๋ฅผ ํธ์ถํด์ ์ฝ๋ ๊ฐ๋ ์ฑ์ ๋์ผ ์๋ ์๋ค. ์ฑ ์ ์ฐธ๊ณ ํ ๋์ ํ๋ก์ ํธ์์๋ ๋ช๋ช ๋ฉ์๋๋ค์ JwtTokenProvider์์ ๊ตฌํํ๊ณ ์ด๋ฅผ ํ ํฐ ํํฐ์์ ํธ์ถํ๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
1. ํ ํฐ์ ์กด์ฌ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ๊ธฐ๋ฅ
๋จผ์ ๋ฉ์๋ ์์์ ๋ค์๊ณผ ๊ฐ์ด POST ์์ฒญ์ผ๋ก๋ถํฐ ํค๋๋ฅผ ๊ฐ์ ธ์์ ํ ํฐ์ ์ถ์ถํ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ค. ํค๋๊ฐ ์กด์ฌํ์ง ์๊ฑฐ๋ ๋ด์ฉ์ด ์ฌ๋ฐ๋ฅธ ํ์์ด ์๋ ์ ์๋ธ๋ฆฟ์ ์คํํ๋ ๋ฉ์๋์ธ filterChain.doFilter() ๋ฅผ ํธ์ถํ๋ค.
2. ํ ํฐ์ ๋ง๋ฃ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ๊ธฐ๋ฅ
๋จผ์ ํ ํฐ์ด ์ฃผ์ด์ก์ ๋ ํ ํฐ์ ๋ง๋ฃ ๋ ์ง๊ฐ ์ธ์ ์ธ์ง ์๊ธฐ ์ํด์๋ ํ ํฐ์ผ๋ก๋ถํฐ Claim ์ ์ถ์ถํ ์ ์์ด์ผ ํ๋ค. ์ด ๊ธฐ๋ฅ์ JwtTokenProvider ์์ ๊ตฌํํ๋ค:
๊ทธ๋ฆฌ๊ณ ์ด ์ถ์ถ๋ ์์ฑ๊ฐ๋ค์์ getExpiration() ์ ์ฌ์ฉํด ๋ง๋ฃ ๋ ์ง๋ฅผ ๊ฐ์ ธ์จ ๋ค ํ์ฌ์ ๋ ์ง์ ๋น๊ตํ๋ค. ์ด๋ฏธ ๋ง๋ฃ ๋ ์ง๊ฐ ํ์ฌ ๋ ์ง๋ณด๋ค ์ด์ ์ ์์ผ๋ฉด ์ด๋ฏธ ๋ง๋ฃ๋ ๊ฒ์ด๋ค. ๋ค์๊ณผ ๊ฐ์ด boolean ํ์ ์ ๋ฉ์๋๋ก ๊ตฌํํ๋ค:
๊ทธ๋ฆฌ๊ณ ์ด ๋ฉ์๋๋ฅผ ํ ํฐ ํํฐ์์ ํธ์ถํด์ ์ฌ์ฉํ๋ค. ๋ค์ ํ ์ค๋ง ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค:
if (JwtTokenProvider.isExpired(token)) filterChain.doFilter(request, response);
3. ์ฌ์ฉ์๋ฅผ ์ธ์ฆํ๋ ๊ธฐ๋ฅ
์ฌ์ฉ์ ์ธ์ฆ์ ๋จ๊ณ๋ ๋ค์๊ณผ ๊ฐ๋ค:
- ์ฌ์ฉ์ ์์ด๋๋ฅผ ํ ํฐ์ผ๋ก๋ถํฐ ์์๋ธ๋ค.
- ์ฌ์ฉ์์ ๊ถํ์ ํ ํฐ์ผ๋ก๋ถํฐ ์์๋ธ๋ค.
- ์์ด๋์ ๊ถํ์ ๊ฐ์ง๊ณ ์ธ์ฆ๋ ํ ํฐ์ด๋ผ๋ ์ฌ์ค์ ๋ํ๋ด๋ ํด๋์ค UsernamePasswordAuthenticationToken ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
- SecurityContextHolder ์ ์ธ์ฆ๋ ํ ํฐ์ ์ ์ฅํ๋ค.
ํ๋์ฉ ์งํํด๋ณด์. ์ฐ์ ์ฌ์ฉ์ ์์ด๋์ ๊ถํ์ ํ ํฐ์ ํด๋ ์์ผ๋ก๋ถํฐ ์์๋ผ ์ ์๋ค. JwtTokenProvider ์ ๋ฉ์๋๋ค์ ์ถ๊ฐํ๋ค:
๋ค์์ผ๋ก ์ธ์ฆ๋ ํ ํฐ์ ๋ํ๋ด๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ JwtTokenProvider ์ ์ถ๊ฐํ๋ค:
๋ง๋ ๋ฉ์๋๋ค์ ํ์ฉํด์ ํ ํฐ ํํฐ์์ SecurityContextHolder ์ ์ธ์ฆ๋ ํ ํฐ์ ์ ์ฅํ๋ค:
๐ฉ ๋ช ๊ฐ์ง ๋ณ๊ฒฝ์ฌํญ๋ค
์ดํ, ์๊ฐํด๋ณด๋ ์ปจํธ๋กค๋ฌ๊ฐ ์๋ ์๋น์ค์์ ํ ํฐ ์์ฑ์ ๊ด๋ฆฌํ๋ ๊ฒ์ด ๋ซ๊ฒ ๋ค๊ณ ํ๋จ๋์๋ค. ๊ทธ๋์ UserService ๋ฅผ ์ถ๊ฐํ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์ปจํธ๋กค๋ฌ์์ ์๋น์ค๋ฅผ DI ๋ฐ์์ ์๋น์ค์์ ๊ตฌํ๋ ๋ฉ์๋๋ฅผ ํตํด ํ ํฐ์ ์์ฑํ๋๋ก ๋ณ๊ฒฝํ๋ค:
๋ํ, ํ ํฐ์ ์์ฑํ๋ JwtTokenProvider ์์์ ๋น๋ฐ ํค์ ํ ํฐ ํํฐ์์ ์ธ์ฆ์ ์ํด ์ฌ์ฉํ๋ ๋น๋ฐ ํค๊ฐ ์ผ์นํ๋๋ก ๋ง๋ค๊ธฐ ์ํด ํ ํฐ ์์ฑ ์ ์๋น์ค์์ ํ๊ฒฝ๋ณ์๋ก๋ถํฐ ๋น๋ฐ ํค๋ฅผ ๊ฐ์ ธ์ createToken ์ ๋งค๊ฐ ๋ณ์๋ก ๋ฃ์ด์ฃผ๋๋ก ๋ณ๊ฒฝํ๋ค. createToken ์ ์ด์ ์ ๋งค๊ฐ๋ณ์๋ก ์ฌ์ฉํ๋ ์ฌ์ฉ์ ์์ด๋, ์ฌ์ฉ์ ๊ถํ ์ธ์๋ ๋น๋ฐ ํค๋ฅผ ๋งค๊ฐ ๋ณ์๋ก ๊ฐ๊ฒ ๋์๋ค. ๊ทธ๋ฆฌ๊ณ ํ ํฐ ํํฐ์์ ๊ฐ์ง๊ณ ์๋ ๋น๋ฐ ํค๋ฅผ ๊ฐ์ง๊ณ JwtTokenProvider ์ ์๋ ์์ฑ์ด ์๋ ์ธ์ฆ์ ์ํ ๋ฉ์๋๋ค์ ๋งค๊ฐ ๋ณ์๋ก ๋ฃ์ด์ฃผ์ด์, ์ธ์ฆ ์์ ์ผ๊ด์ ์ผ๋ก ํ๋์ ๋น๋ฐ ํค๋ก ์ฌ๋ฐ๋ฅธ ๋ฐฉ์์ผ๋ก ์ธ์ฆ์ ํ ์ ์๋๋ก ๋ณ๊ฒฝํด์ฃผ์๋ค. ์ด์ ํ ํฐ์ ์์ฑํ ๋์ ์ธ์ฆํ ๋ ๊ฐ์ ๋น๋ฐ ํค๋ฅผ ์ฌ์ฉํ๋ค.
๋ณ๊ฒฝ๋ JwtTokenProvider ๋ ์๋์ ๊ฐ๋ค:
์ด์ ๋ค์ Swagger ๋ฅผ ์คํํด๋ณด์. ์ด์ ๊ณผ ๋ค๋ฅด๊ฒ addFilterBefore ์ด ์์ด๋ ํ๋ฉด์ด ๋์ค๋ ๊ฒ์ ๋ณผ ์ ์์ ๊ฒ์ด๋ค:
๐ ํน์ API์์ ์ธ์ฆ ์์ฒญํ๊ธฐ
์ด์ ํน์ POST API ์์ฒญ์์ ์ด์ ์ ์๋ฒ์์ ๋ฐํ๋ ํ ํฐ์ ๊ฐ์ง๊ณ ์ธ์ฆ๋ฐ์ง ์์ผ๋ฉด ์์ฒญํ ์ ์๋๋ก ๋ง๋ค์ด๋ณด์. ์ด ํ๋ก์ ํธ์์๋ ๊ฒ์ํ์ ๋ก๊ทธ์ธ๋ ์ฌ์ฉ์๋ง ๋๊ธ์ ๋ฌ ์ ์๋ ์ํฉ์ ๊ฐ์ ํ๋ค. ์ฐ์ SecurityConfig ํด๋์ค์์ ๋ณด์ ํํฐ์ ์์ฑ๊ฐ ํ๋๋ฅผ ๋ณ๊ฒฝํ์ฌ ํน์ URL ๋ก ์ค๋ POST ์์ฒญ์ ์ธ์ฆ์ ๊ฑฐ์ณ์ผ๋ง ๊ฐ๋ฅํ๋๋ก ๋ง๋ ๋ค:
.antMatchers(HttpMethod.POST, "/api/v1/comments/new").authenticated()
์ดํ ์ปจํธ๋กค๋ฌ๋ฅผ ํ๋ ๋ง๋ค๊ณ ์์ URL ๋ก ์์์ POST ์์ฒญ์ ๋ณด๋ด๋ ์ํฉ์ ๊ตฌํํ๋ค:
์ด์ ๋ค์ Swagger ๋ฅผ ์ด๊ณ , ๋๊ธ์ ์๋ฌด๋ ๋ฌ ์ ์๋์ง, ์ธ์ ์ธ์ฆ์ด ๋๋์ง๋ฅผ ํ์ธํด๋ณด๋ คํ์ง๋ง, Swagger ์์๋ ํค๋ ์ค์ ์ด ๊น๋ค๋ก์์ Talend API tester ๋ก ์งํํ๋ค:
'Web Framework' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
- Total
- Today
- Yesterday
- google cloud
- ํ๋ก๊ทธ๋๋จธ์ค
- Java Data Types
- ์ธ์ฆ/์ธ๊ฐ
- ์ง์ฐ ๋ก๋ฉ
- spring
- gitlab
- JOIN FETCH
- ์ฝํ
- ์๊ณ ๋ฆฌ์ฆ
- Jackson
- DeSerialization
- N+1
- DTO
- ๊ฐ์ ์๋ฒ
- ์ญ์ง๋ ฌํ
- ๊ธฐ์ง๊ตญ ์ค์น
- ๋์ปค
- ci/cd
- docker
- json web token
- JPA
- @RequestBody
- FCM
- JPQL
- ๊น๋ฉ
- LazyInitializationException
- ์ค์๊ฐ๋ฐ์ดํฐ
- Spring Boot
- Firebase
์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |