[8/8 TIL] SPRING SECURITY(HTTP์™€ Session, Spring Session)

yumyeonghanยท2023๋…„ 8์›” 9์ผ
0
post-custom-banner

๐Ÿƒํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐฑ์—”๋“œ ๋ฐ๋ธŒ์ฝ”์Šค 4๊ธฐ ๊ต์œก๊ณผ์ •์„ ๋“ฃ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.๐Ÿƒ

HTTP์™€ Session

๊ทธ๋ฆผ ์ฐธ๊ณ 

  • ๊ทผ๋ณธ์ ์œผ๋กœ HTTP๋Š” ๋ฌด์ƒํƒœ ํ”„๋กœํ† ์ฝœ์ด๊ณ  ์–ด๋–ค ์ •๋ณด๋„ ์ €์žฅํ•˜์ง€ ์•Š์Œ
  • ์„œ๋ฒ„๋Š” ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด Session์„ ๋งŒ๋“ค๊ณ , ์‹๋ณ„์ž์ธ session-id๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ์‘๋‹ตํ•จ
  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›น ๋ธŒ๋ผ์šฐ์ €์ธ ๊ฒฝ์šฐ session-id๋Š” ๋ณดํ†ต Cookie ์— ์ €์žฅ๋จ
  • ํด๋ผ์ด์–ธํŠธ๋Š” HTTP ์š”์ฒญ์— session-id๋ฅผ ํฌํ•จ์‹œ์ผœ, ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผํ•จ
  • Session์€ ์„œ๋ฒ„ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋„ˆ๋ฌด ๋งŽ์•„์งˆ ๊ฒฝ์šฐ ์„œ๋ฒ„ ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ

ํŠน์ • ์„œ๋ฒ„์—์„œ ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๊ฑฐ๊ธฐ์— ์žˆ๋˜ Session์€ ์œ ์‹ค์ด ๋ ํ…๋ฐ ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ?

Session Cluster

๊ทธ๋ฆผ ์ฐธ๊ณ 

  • Session์„ ์„œ๋ฒ„ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•„๋‹Œ, ๋ณ„๋„์˜ ์™ธ๋ถ€ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅ
  • ์™ธ๋ถ€ ์Šคํ† ๋ฆฌ์ง€๋Š” ์กฐํšŒ ์†๋„๋ฅผ ์œ„ํ•ด ๋ณดํ†ต In-Memory ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•จ
    • In-Memory ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋””์Šคํฌ๊ฐ€ ์•„๋‹Œ, ์ฃผ ๋ฉ”๋ชจ๋ฆฌ์— ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์œ ํ•˜๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
    • ์ผ๋ฐ˜์ ์ธ ๋””์Šคํฌ ์กฐํšŒ๋ณด๋‹ค ์†๋„๊ฐ€ ํ›จ์”ฌ ๋น ๋ฅด์ง€๋งŒ, ํœ˜๋ฐœ์„ฑ์ด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„๊ฐ€ ๊บผ์ ธ์„œ ๋‚ ์•„๊ฐ€๋„ ์ƒ๊ด€์—†๋Š” ๋ฐ์ดํ„ฐ (์ฟ ํ‚ค, ์„ธ์…˜)์— ์‚ฌ์šฉ
    • ๋Œ€ํ‘œ์ ์œผ๋กœ Redis๊ฐ€ ์žˆ์Œ
  • ํŠน์ • ์„œ๋ฒ„์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ๋„ ๋‹ค๋ฅธ ์ •์ƒ์ ์ธ ์„œ๋ฒ„์—์„œ Session์„ ์™ธ๋ถ€ ์Šคํ† ๋ฆฌ์ง€์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‚ฌ์šฉ์ž ์ธ์ฆ์ด ํ’€๋ฆฌ์ง€ ์•Š์Œ

Spring Session

  • Spring Session๋Š” Spring Boot ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Session Cluster๋ฅผ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณต
  • Session์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ์™ธ๋ถ€ ์Šคํ† ๋ฆฌ์ง€๋ฅผ ์ถ”์ƒํ™”ํ•จ์œผ๋กœ์จ ์ผ๊ด€๋œ API๋กœ JDBC, Redis, Hazelcast ๋“ฑ ๋‹ค์–‘ํ•œ ์Šคํ† ๋ฆฌ์ง€๋ฅผ ํ™œ์šฉ ๊ฐ€๋Šฅ

์„ค์ • ๋ฐฉ๋ฒ•

  1. gradle ์˜์กด์„ฑ ์ถ”๊ฐ€ ๋ฐ ์„ค์ •

  2. Spring Session ๊ด€๋ จ ํ…Œ์ด๋ธ” ์ดˆ๊ธฐํ™”

spring:
  sql:
    init:
      platform: h2
      mode: always
      schema-locations: classpath:sql/schema_new.sql, classpath:org/springframework/session/jdbc/schema-h2.sql
      data-locations: classpath:sql/data_new.sql
      encoding: UTF-8
      mode: always
  • spring-session-jdbc๋Š” session ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด 2๊ฐœ์˜ ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•จ
    • sql.init.schema-locations ๋ถ€๋ถ„์— spring-session-jdbc์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ…Œ์ด๋ธ” ์ƒ์„ฑ SQL ์ฟผ๋ฆฌ ํŒŒ์ผ์„ ์ง€์ •
    • ํ…Œ์ด๋ธ”์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•œ SQL ์ฟผ๋ฆฌ๋Š” spring-session-jdbc jar ๋‚ด๋ถ€์— ์œ„์น˜ํ•จ

spring:
  session:
    store-type: jdbc
    jdbc:
      initialize-schema: never
  • Spring Session ๊ด€๋ จ ์„ค์ •
    • session.store-type ๋ถ€๋ถ„์— jdbc๋ฅผ ์ž…๋ ฅํ•จ
      • jdbc ์™ธ์— ์ž…๋ ฅ ๊ฐ€๋Šฅํ•œ ๊ฐ’์€ redis, mongodb, hazelcast๋“ฑ ์ด ์žˆ์Œ
    • session.jdbc.initialize-schema ๋ถ€๋ถ„์— never๋ฅผ ์ž…๋ ฅํ•จ
      • sql.init.schema-locations๋ถ€๋ถ„์— spring-session-jdbc์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ…Œ์ด๋ธ” ์ƒ์„ฑ SQL ์ฟผ๋ฆฌ ํŒŒ์ผ์„ ์ง€์ •ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ
  1. @EnableJdbcHttpSession ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜์—ฌ, jdbc๊ธฐ๋ฐ˜ spring session์„ ํ™œ์„ฑํ™”
@Configuration
@EnableJdbcHttpSession
public class WebMvcConfigure {
}

h2 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™•์ธ


  • ๋กœ๊ทธ์ธ ํ›„ h2-console์—์„œ SPRING_SESSION, SPRING_SESSION_ATTRIBUTES ํ…Œ์ด๋ธ” ์กฐํšŒํ•ด๋ณด๋ฉด, row๊ฐ€ ์ž…๋ ฅ๋˜ ์žˆ๋Š”๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ
    • session_id โ€” ์‚ฌ์šฉ์ž์˜ Session์„ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ ๊ณ ์œ  Key
    • ๋ธŒ๋ผ์šฐ์ € Cookie๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด session_id ๊ฐ’์ด Base64 ์ธ์ฝ”๋”ฉ๋œ ํ˜•ํƒœ๋กœ ์ €์žฅ๋˜์–ด ์žˆ์Œ

SessionRepository

public interface SessionRepository<S extends Session> {

	S createSession();

	void save(S session);

	S findById(String id);

	void deleteById(String id);

}
  • Session์˜ ์ƒ์„ฑ, ์ €์žฅ, ์กฐํšŒ, ์‚ญ์ œ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ์ฑ…์ž„
  • ์Šคํ† ๋ฆฌ์ง€ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ๊ตฌํ˜„์ฒด๋ฅผ ์ œ๊ณตํ•จ
    • MapSessionRepository: In-Memory Map๊ธฐ๋ฐ˜์ด๋ฉฐ, ๋ณ„๋„์˜ ์˜์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•„์š” ์—†์Œ
    • RedisIndexedSessionRepository: redis ๊ธฐ๋ฐ˜์ด๋ฉฐ, @EnableRedisHttpSession ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ƒ์„ฑ๋จ
    • JdbcIndexedSessionRepository: jdbc ๊ธฐ๋ฐ˜์ด๋ฉฐ, @EnableJdbcHttpSession ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ƒ์„ฑ๋จ

SessionRepositoryFilter

๊ทธ๋ฆผ ์ฐธ๊ณ 

  • ๋ชจ๋“  HTTP ์š”์ฒญ์— ๋Œ€ํ•ด ๋™์ž‘ํ•จ
  • HttpServletRequest, HttpServletResponse ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์„ SessionRepositoryRequestWrapper, SessionRepositoryResponseWrapper ๊ตฌํ˜„์ฒด๋กœ ๊ต์ฒดํ•จ
  • ๊ต์ฒด๋œ ๊ตฌํ˜„์ฒด๋Š” HttpServletRequest, HttpServletResponse ์ธํ„ฐํŽ˜์ด์Šค์˜ Session ์ฒ˜๋ฆฌ์™€ ๊ด€๋ จํ•œ ๋กœ์ง์„ Overrideํ•จ
    • Session ๊ด€๋ จ ์ƒ์„ฑ ๋ฐ ์ž…์ถœ๋ ฅ์€ SessionRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•จ
    • HttpSession ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•ด Spring Session ๊ตฌํ˜„์ฒด HttpSessionWrapper๋ฅผ ์‚ฌ์šฉํ•˜๋„๋กํ•จ

Spring Security์˜ SecurityContextHolderFilter๋Š” SecurityContextRepository ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ฒด์ธ, HttpSessionSecurityContextRepository ํด๋ž˜์Šค ํ†ตํ•ด ์‚ฌ์šฉ์ž์˜ SecurityContext๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ๊ฐฑ์‹ ํ•จ

  • HttpServletRequest ์ธํ„ฐํŽ˜์ด์Šค์˜ getSession() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด Session์„ ๊ฐ€์ ธ์˜ด
  • ๋ฐ”๋กœ ์ด ์ง€์ ์—์„œ HttpServletRequest ์ธํ„ฐํŽ˜์ด์Šค์˜ ์Šคํ”„๋ง ์„ธ์…˜ ๊ตฌํ˜„์ฒด์ธ SessionRepositoryRequestWrapper ํด๋ž˜์Šค๊ฐ€ ์‚ฌ์šฉ๋จ
  • ๊ฒฐ๊ณผ์ ์œผ๋กœ, Spring Security๋Š” HttpServletRequest ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ฒด๋ฅผ ์•Œ ํ•„์š”๊ฐ€ ์—†๊ณ , ๊ทธ๋ƒฅ ์‚ฌ์šฉํ•˜๋ฉด ๋จ
profile
์›น ๊ฐœ๋ฐœ์— ๊ด€์‹ฌ ์žˆ์Šต๋‹ˆ๋‹ค.
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€