π[Spring Security] Spring Securityλ?
λͺ©μ°¨
- Spring Security κ°μ
- ν΅μ¬ κ°λ : μΈμ¦κ³Ό μΈκ°
- λμ μ리: μλΈλ¦Ώ νν° μ²΄μΈ
- μ¬μ©ν΄μΌ νλ μ΄μ
- μμ½
Spring Security κ°μ
Spring Securityλ Spring κΈ°λ° μ ν리μΌμ΄μ μ 보μ(μΈμ¦κ³Ό μΈκ°)μ μ λ΄νλ κ°λ ₯νκ³ νμμ μΈ νλ μμν¬μ λλ€.
π― ν΅μ¬ μν
βμ°λ¦¬ μ ν리μΌμ΄μ μ λ¬Έμ§κΈ°μ΄μ μ κ·Ό μ μ΄ κ΄λ¦¬μβ
Spring Securityκ° μλ€λ©΄?
- κ°λ°μκ° μ§μ μΈμ κ΄λ¦¬ μ½λ μμ±
- URLλ§λ€ κΆν μ²΄ν¬ λ‘μ§ μ€λ³΅ μμ±
- λͺ¨λ 컨νΈλ‘€λ¬μ μλΉμ€μ 보μ μ½λκ° λ€μμ
Spring Securityλ μ΄ λͺ¨λ κ²μ μ ν리μΌμ΄μ μ ν΅μ¬ λ‘μ§κ³Ό λΆλ¦¬νμ¬ μ²΄κ³μ μΌλ‘ μ²λ¦¬ν©λλ€.
ν΅μ¬ κ°λ : μΈμ¦κ³Ό μΈκ°
Spring Securityμ μ‘΄μ¬ μ΄μ λ λ°λ‘ μ΄ λ κ°μ§ κ°λ μ ν΄κ²°νκΈ° μν¨μ λλ€.
1οΈβ£ μΈμ¦ (Authentication)
βλΉμ μ λꡬμλκΉ?β
μ¬μ©μκ° μμ μ μ μμ μ¦λͺ νλ κ³Όμ μ λλ€.
μΈμ¦ λ°©λ² μμ
- ID/Password μ λ ₯
- μμ λ‘κ·ΈμΈ (OAuth2)
- JWT ν ν° μ μΆ
- μ체 μΈμ¦
λμ κ³Όμ
- μ¬μ©μκ° λ‘κ·ΈμΈ μμ²
- Spring Securityκ° μμ²μ κ°λ‘μ±μ Credentials κ²μ¦
- μΈμ¦ μ±κ³΅ μ
SecurityContext
μAuthentication
κ°μ²΄ μ μ₯
// μΈμ¦ μ 보 μ‘°ν μμ
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = authentication.getName();
2οΈβ£ μΈκ° (Authorization)
βλΉμ μ΄ μ΄ μμ μ ν κΆνμ΄ μμ΅λκΉ?β
μΈμ¦λ μ¬μ©μκ° νΉμ 리μμ€μ μ κ·Όν κΆνμ΄ μλμ§ νμΈνλ κ³Όμ μ λλ€.
κΆν μ²΄ν¬ μμ
-
/admin
βROLE_ADMIN
κΆν νμ -
/my-page
βROLE_USER
κΆνμΌλ‘ μΆ©λΆ -
/public
β λꡬλ μ κ·Ό κ°λ₯
μ€μ λ°©λ²
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}
// λ©μλ λ 벨 보μ
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long userId) {
// ADMINλ§ μ€ν κ°λ₯
}
λμ μ리: μλΈλ¦Ώ νν° μ²΄μΈ
μ΄κ²μ΄ Spring Securityμ κ°μ₯ μ€μν μν€ν μ²μ λλ€.
π ν΅μ¬ κ°λ
Spring Securityλ FilterChainProxyλΌλ νλμ κ±°λν νν°λ₯Ό μλΈλ¦Ώ 컨ν μ΄λ(Tomcat)μ λ±λ‘ν©λλ€.
μ΄ νν° λ΄λΆμλ μ¬λ¬ κ°μ 보μ νν°λ€λ‘ ꡬμ±λ 체μΈ(Chain)μ΄ μ‘΄μ¬ν©λλ€.
π μμ² μ²λ¦¬ νλ¦
λͺ¨λ μΉ μμ²μ 컨νΈλ‘€λ¬μ λλ¬νκΈ° μ μ λ°λμ μ΄ νν° μ²΄μΈμ ν΅κ³Όν©λλ€.
Client Request
β
βββββββββββββββββββββββββββββββββββ
β Spring Security Filter Chain β
βββββββββββββββββββββββββββββββββββ€
β 1. CorsFilter β
β 2. CsrfFilter β
β 3. JwtAuthenticationFilter β
β 4. UsernamePasswordAuthFilter β
β 5. ExceptionTranslationFilter β
β 6. AuthorizationFilter β
βββββββββββββββββββββββββββββββββββ
β
DispatcherServlet
β
Controller
π‘ JWT κΈ°λ° μΈμ¦ μ νν° μ²΄μΈ λμ μμ
1λ¨κ³: μμ² μμ
ν΄λΌμ΄μΈνΈκ° Authorization ν€λμ JWTλ₯Ό λ΄μ μμ²
GET /api/user/profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
2λ¨κ³: νν° μ²΄μΈ ν΅κ³Ό
β CorsFilter
- CORS μ μ± νμΈ
- Cross-Origin μμ² νμ© μ¬λΆ κ²μ¦
β‘ CsrfFilter
- CSRF ν ν° κ²μ¦ (Stateless νκ²½μμλ λ³΄ν΅ λΉνμ±ν)
β’ JwtAuthenticationFilter (컀μ€ν νν°)
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) {
// 1. ν€λμμ JWT μΆμΆ
String token = extractToken(request);
// 2. JWT μ ν¨μ± κ²μ¦
if (token != null && jwtTokenProvider.validateToken(token)) {
// 3. ν ν°μμ μ¬μ©μ μ 보 μΆμΆ
Authentication auth = jwtTokenProvider.getAuthentication(token);
// 4. SecurityContextμ μΈμ¦ μ 보 μ μ₯
SecurityContextHolder.getContext().setAuthentication(auth);
}
filterChain.doFilter(request, response);
}
}
β£ ExceptionTranslationFilter
- μΈμ¦/μΈκ° κ³Όμ μμ λ°μνλ μμΈ μ²λ¦¬
-
AuthenticationException
,AccessDeniedException
μ²λ¦¬
β€ AuthorizationFilter (κ³Όκ±° FilterSecurityInterceptor
)
// μ¬μ©μκ° μμ²ν URLμ μ κ·Ό κΆνμ΄ μλμ§ μ΅μ’
νμΈ
// μ: /admin/** β ROLE_ADMIN κΆν νμ
3λ¨κ³: 컨νΈλ‘€λ¬ λλ¬
λͺ¨λ νν°λ₯Ό ν΅κ³Όνλ©΄ DispatcherServletμ κ±°μ³ Controllerμ λ‘μ§μ΄ μ€νλ©λλ€.
@RestController
@RequestMapping("/api/user")
public class UserController {
@GetMapping("/profile")
public UserProfile getProfile() {
// SecurityContextμμ μΈμ¦λ μ¬μ©μ μ 보 μ‘°ν
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
return userService.getProfile(username);
}
}
μ¬μ©ν΄μΌ νλ μ΄μ
β 1. νμ€νλ 보μ
κ²μ¦λκ³ νμ€νλ λ°©μμΌλ‘ 보μμ μ μ©νμ¬ κ°λ°μμ μ€μλ‘ μΈν 보μ νμ μ μ΅μνν©λλ€.
β 2. κ΄μ¬μ¬μ λΆλ¦¬ (Separation of Concerns)
보μ λ‘μ§μ΄ λΉμ¦λμ€ λ‘μ§(컨νΈλ‘€λ¬, μλΉμ€)κ³Ό μλ²½νκ² λΆλ¦¬λ©λλ€.
// β Spring Security μμ΄
@GetMapping("/admin/users")
public List<User> getUsers(HttpSession session) {
// 보μ λ‘μ§μ΄ λΉμ¦λμ€ λ‘μ§κ³Ό μμ
if (session.getAttribute("user") == null) {
throw new UnauthorizedException();
}
User user = (User) session.getAttribute("user");
if (!"ADMIN".equals(user.getRole())) {
throw new ForbiddenException();
}
return userService.getAllUsers();
}
// β
Spring Security μ¬μ©
@GetMapping("/admin/users")
@PreAuthorize("hasRole('ADMIN')")
public List<User> getUsers() {
return userService.getAllUsers(); // λΉμ¦λμ€ λ‘μ§λ§ μ§μ€
}
β 3. κ°λ ₯ν λ°©μ΄ κΈ°λ₯
μΉμ κ³ μ μ μΈ λ³΄μ 곡격μ κΈ°λ³Έμ μΌλ‘ λ°©μ΄ν©λλ€.
- CSRF (Cross-Site Request Forgery) λ°©μ΄
- μΈμ κ³ μ (Session Fixation) 곡격 λ°©μ΄
- ν΄λ¦μ¬νΉ (Clickjacking) λ°©μ΄
- XSS (Cross-Site Scripting) λ³΄νΈ ν€λ μλ μ€μ
β 4. λμ νμ₯μ±
νν°λ₯Ό μ§μ μΆκ°νκ±°λ μΈμ¦ λ°©μμ 컀μ€ν°λ§μ΄μ§νλ κ²μ΄ λ§€μ° μ μ°ν©λλ€.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// 컀μ€ν
νν° μΆκ°
.addFilterBefore(jwtAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class)
// OAuth2 λ‘κ·ΈμΈ μ€μ
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userService(customOAuth2UserService)
)
)
// JWT μΈμ¦ μ€μ
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
);
return http.build();
}
}
μμ½
π― Spring Securityλ?
Spring Securityλ Spring μ ν리μΌμ΄μ 보μμ μ¬μ€μ νμ€μ΄λ©°, μΈμ¦/μΈκ°λ₯Ό μν νμ μΈνλΌλ₯Ό μ 곡νλ νλ μμν¬μ λλ€.
π ν΅μ¬ ν¬μΈνΈ
κ΅¬λΆ | μ€λͺ |
---|---|
ν΅μ¬ κΈ°λ₯ | μΈμ¦(Authentication) + μΈκ°(Authorization) |
λμ λ°©μ | μλΈλ¦Ώ νν° μ²΄μΈμ ν΅ν μμ² κ°λ‘μ±κΈ° |
μ£Όμ μ₯μ | νμ€ν, κ΄μ¬μ¬ λΆλ¦¬, κ°λ ₯ν λ°©μ΄, λμ νμ₯μ± |
μ μ© λ²μ | URL κΈ°λ°, λ©μλ κΈ°λ° λ³΄μ λͺ¨λ μ§μ |
π λ€μ νμ΅ μ£Όμ
- Spring Security Configuration μ¬ν
- JWT μΈμ¦ ꡬν
- OAuth2 / OpenID Connect
- Method Security (
@PreAuthorize
,@Secured
) - Custom Filter ꡬν
- Password Encoding (BCrypt)
- Remember-Me μΈμ¦
μ°Έκ³ : μ΄ λ¬Έμλ Spring Securityμ κΈ°λ³Έ κ°λ μ λ€λ£Ήλλ€. μ€μ νλ‘μ νΈ μ μ© μμλ 보μ μꡬμ¬νμ λ§κ² μΈλΆ μ€μ μ μ‘°μ ν΄μΌ ν©λλ€.