[8/9 TIL] SPRING SECURITY(Stateful, Stateless, JWT, REST API with JWT, JwtAuthenticationFilter)

yumyeonghanยท2023๋…„ 8์›” 12์ผ
0

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

Stateful, Stateless

Stateful ์•„ํ‚คํ…์ฒ˜

  • Session์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉด, Stateful ํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Œ
  • ์ˆ˜ํ‰ํ™•์žฅ(Scale-Out) ๊ณผ์ •์ด ์‰ฝ์ง€ ์•Š์Œ
    • Session Cluster ๋ฐ˜๋“œ์‹œ ํ•„์š”
    • Session Cluster์˜ ์žฅ์•  ๋˜๋Š” ์„ฑ๋Šฅ ๋ณ‘๋ชฉ์ด ์„œ๋น„์Šค ์ „์ฒด์— ํฐ ์˜ํ–ฅ์„ ์ค„์ˆ˜ ์žˆ์Œ
  • ๋‹จ์ผ ์‚ฌ์šฉ์ž์˜ ๋‹ค์ค‘ ๋กœ๊ทธ์ธ ์ปจํŠธ๋กค, ์‚ฌ์šฉ์ž ์œ ํšจ์„ฑ ์ฒดํฌ, ๊ฐ•์ œ ๋กœ๊ทธ์•„์›ƒ ๊ธฐ๋Šฅ ๊ตฌํ˜„์ด ์‰ฌ์›€

Stateless ์•„ํ‚คํ…์ฒ˜

  • Session์„ ์ „ํ˜€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์•ผํ•จ
    • HTTP ํ”„๋กœํ† ์ฝœ ์ž์ฒด๊ฐ€ Stateless
  • ์ˆ˜ํ‰ํ™•์žฅ์ด ๋งค์šฐ ์‰ฌ์›€
    • Session Cluster ํ•„์š” ์—†์Œ
  • ๋‹จ์ผ ์‚ฌ์šฉ์ž์˜ ๋‹ค์ค‘ ๋กœ๊ทธ์ธ ์ปจํŠธ๋กค, ์‚ฌ์šฉ์ž ์œ ํšจ์„ฑ ์ฒดํฌ, ๊ฐ•์ œ ๋กœ๊ทธ์•„์›ƒ ๊ธฐ๋Šฅ ๊ตฌํ˜„์ด ์–ด๋ ค์›€
  • ์™„์ „ํ•œ Stateless ์•„ํ‚คํ…์ฒ˜ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ์˜๋ฏธํ•œ ์„œ๋น„์Šค ๊ฐœ๋ฐœ์ด ์–ด๋ ค์›€
    • ์™„์ „ํ•œ Stateless ์„œ๋น„์Šค๋Š” ์ •์  ๋ฆฌ์†Œ์Šค(html, css, javascript, ์ด๋ฏธ์ง€ ๋“ฑ)๋ฅผ AWS S3๋กœ ์„œ๋น„์Šค ํ•˜๋Š”๋ฐ ์ ํ•ฉํ•จ
    • ์„œ๋ฒ„๋Š” ์–ด๋–ค์‹์œผ๋กœ๋Š” ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•จ (๋‹จ, Session ์‚ฌ์šฉ ๊ธˆ์ง€)

JWT (Json Web Token)

๊ทธ๋ฆผ ์ฐธ๊ณ 

  • JWT๋Š” Stateless ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ, ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋‹จ์„ ์ œ๊ณต
  • ๋™์ž‘ ๊ณผ์ •
    • ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ธ์ฆ๋˜๋ฉด JWT๋ฅผ ๋ฐ˜ํ™˜ํ•จ
    • ํด๋ผ์ด์–ธํŠธ๋Š” JWT๋ฅผ ๋กœ์ปฌ ์˜์—ญ์— ์ €์žฅํ•˜๊ณ , ์ดํ›„ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ JWT๋ฅผ HTTP ํ—ค๋”์— ํฌํ•จ์‹œํ‚ด
    • ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ „๋‹ฌํ•œ JWT๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Œ

JWT ๊ฐœ์š”

  • ์ž์ฒด ํฌํ•จํ˜• (Self-Contained): JWT๋Š” ํ† ํฐ์— ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋‚ด๋ถ€์— ํฌํ•จํ•˜์—ฌ ์ €์žฅ

    • ํ† ํฐ์— ๋Œ€ํ•œ ๋ฉ”ํƒ€์ •๋ณด(ํ† ํฐ ํƒ€์ž…, ์‚ฌ์šฉ๋œ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜), ์‚ฌ์šฉ์ž ์ •์˜ ๋ฐ์ดํ„ฐ ๋ฐ ํ† ํฐ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์„ ์œ„ํ•œ ๋ฐ์ดํ„ฐ ๋“ฑ์„ ํฌํ•จํ•จ
  • ์ธํ„ฐ๋„ท ์ „๋‹ฌ ์šฉ์ด์„ฑ: JWT๋Š” URL-Safeํ•œ ํ…์ŠคํŠธ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์–ด HTTP ํ”„๋กœํ† ์ฝœ์˜ ์–ด๋Š ์œ„์น˜์—๋“  ์‰ฝ๊ฒŒ ์ „๋‹ฌ ๊ฐ€๋Šฅ

    • ์ผ๋ฐ˜์ ์œผ๋กœ HTTP ํ—ค๋”์— ํฌํ•จ๋˜์–ด ์‚ฌ์šฉ
  • ์œ„๋ณ€์กฐ ๊ฒ€์ฆ ๊ฐ€๋Šฅ: JWT๋Š” ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋ช…(Signature)์„ ํฌํ•จํ•˜๋ฉฐ, ์ด ์„œ๋ช…์„ ํ†ตํ•ด ํ† ํฐ์ด ์œ„๋ณ€์กฐ๋˜์ง€ ์•Š์•˜์Œ์„ ๊ฒ€์ฆ

    • ํ† ํฐ์˜ ๋‚ด์šฉ์ด ์ˆ˜์ •๋˜๋ฉด ์„œ๋ช…์ด ๋ฌดํšจํ™”๋˜๋ฏ€๋กœ ์œ„๋ณ€์กฐ ์—ฌ๋ถ€๋ฅผ ํ™•์ธ

JWT ๊ตฌ์กฐ

  • Header, Payload, Signature ์„ธ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋จ
  • Header, Payload, Signature ์„ธ ๋ถ€๋ถ„์„ Base64 Url-Safe ๋ฐฉ์‹์œผ๋กœ ์ธ์ฝ”๋”ฉํ•˜๊ณ  dot(.)์„ ๊ตฌ๋ถ„์ž๋กœ ๊ฒฐํ•ฉํ•จ
  • Header: JWT๋ฅผย ๊ฒ€์ฆํ•˜๋Š”๋ฐย ํ•„์š”ํ•œย ์ •๋ณด๋ฅผย ๋‹ด๊ณ ย ์žˆ์Œ (ํ† ํฐย ํƒ€์ž…,ย ์‚ฌ์šฉ๋œย ์•Œ๊ณ ๋ฆฌ์ฆ˜)
    • ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ HMAC, RSA ๋ฐฉ์‹์„ ์ง€์›
    • ์œ„์˜ ๊ทธ๋ฆผ์—์„œ HS512๋Š” HMAC using SHA-512๋ฅผ ์˜๋ฏธ
    • HMAC ์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ ๋น„๋ฐ€ํ‚ค๋Š” ์ตœ์†Œํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์„œ๋ช… ๊ธธ์ด๋งŒํผ์˜ ๋น„ํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผํ•จ (HS512 โ€” 64byte)
  • Payload: JWT๋ฅผ ํ†ตํ•ด ์ „๋‹ฌํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฐ์ดํ„ฐ, Claim-Set(Key-Value) ์ด๋ผ๊ณ  ํ•จ
    • JWT ์ž์ฒด๋Š” ์•”ํ˜ธํ™”๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฏผ๊ฐ์ •๋ณด๋ฅผ ํฌํ•จํ•ด์„œ๋Š” ์•ˆ๋จ
    • Reserved Claims, Public Claims, Custom Claims ์œผ๋กœ ๊ตฌ๋ถ„๋จ
    • Reserved Claims: ๋ฏธ๋ฆฌ ๋“ฑ๋ก๋œ Claims์œผ๋กœ, ํ•„์ˆ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•  ํ•„์š”๋Š” ์—†์ง€๋งŒ ์‚ฌ์šฉ์„ ๊ถŒ๊ณ ํ•จ
      • iss: ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•œ ๋ฐœ๊ธ‰์ž (Issuer)
      • exp: ๋งŒ๋ฃŒ์‹œ๊ฐ„์ด ์ง€๋‚œ ํ† ํฐ์€ ์‚ฌ์šฉ๋ถˆ๊ฐ€
      • nbf: Not Before์˜ ์˜๋ฏธ๋กœ ํ•ด๋‹น ์‹œ๊ฐ„ ์ด์ „์—๋Š” ํ† ํฐ ์‚ฌ์šฉ๋ถˆ๊ฐ€
      • iat: ํ† ํฐ์ด ๋ฐœ๊ธ‰๋œ ์‹œ๊ฐ
      • jti: JWT ID๋กœ ํ† ํฐ์— ๋Œ€ํ•œ ์‹๋ณ„์ž
    • Public Claims: ์‚ฌ์šฉ์ž ๋งˆ์Œ๋Œ€๋กœ ์“ธ ์ˆ˜ ์žˆ์œผ๋‚˜ ์ถฉ๋Œ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด ๋ฏธ๋ฆฌ ์ •์˜๋œ ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉ์„ ๊ถŒ๊ณ ํ•จ
    • Custom Claims: ์‚ฌ์šฉ์ž ์ •์˜ Claims์œผ๋กœ, Reserved, Public ์— ์ •์˜๋œ ์ด๋ฆ„๊ณผ ์ค‘๋ณต๋˜์ง€ ์•Š๋„๋กํ•จ
  • Signature: ํ† ํฐ ์ƒ์„ฑ ์ฃผ์ฒด๋งŒ ์•Œ๊ณ  ์žˆ๋Š” ๋น„๋ฐ€ํ‚ค๋ฅผ ์ด์šฉํ•ด ํ—ค๋”์— ์ •์˜๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ์„œ๋ช…๋œ ๊ฐ’
    • ํ† ํฐ์ด ์œ„๋ณ€์กฐ ๋˜์ง€ ์•Š์•˜์Œ์„ ์ฆ๋ช…ํ•จ

JWT ์žฅ๋‹จ์ 

  • ์žฅ์ 

    • ์ž์ฒด ํฌํ•จํ˜• ๋ฐ์ดํ„ฐ

      • JWT๋Š” ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ํ† ํฐ ์ž์ฒด์— ํฌํ•จ
      • ์„œ๋ฒ„๋Š” ๋ณ„๋„์˜ ์Šคํ† ๋ฆฌ์ง€๋‚˜ ์„ธ์…˜ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์œ ์ง€ํ•  ํ•„์š”๊ฐ€ ์—†์Œ
      • ์ด๋Š” ์ˆ˜ํ‰ ํ™•์žฅ์„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์„œ๋ฒ„์˜ ํ™•์žฅ์„ฑ์„ ํ–ฅ์ƒ ์‹œํ‚ด
    • Active User ๊ด€๋ฆฌ ์šฉ์ด์„ฑ

      • ์„ธ์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ Active User๋งˆ๋‹ค ์„ธ์…˜์„ ์ €์žฅํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šคํ† ๋ฆฌ์ง€ ๊ด€๋ฆฌ๊ฐ€ ๋ณต์žกํ•จ
      • ํ•˜์ง€๋งŒ JWT๋Š” ํ† ํฐ ์ž์ฒด๊ฐ€ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋ฏ€๋กœ ์Šคํ† ๋ฆฌ์ง€ ๊ด€๋ฆฌ๊ฐ€ ํ›จ์”ฌ ๊ฐ„๋‹จํ•จ
  • ๋‹จ์ 

    • ํ† ํฐ ํฌ๊ธฐ ์ œํ•œ

      • JWT๋ฅผ ํ•ญ์ƒ HTTP ์š”์ฒญ์— ํฌํ•จํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ† ํฐ ํฌ๊ธฐ๋ฅผ ์ž‘๊ฒŒ ์œ ์ง€ํ•ด์•ผ ํ•จ
      • ํ† ํฐ์ด ์ปค์ง€๋ฉด ๋„คํŠธ์›Œํฌ ๋ถ€ํ•˜๊ฐ€ ์ฆ๊ฐ€ํ•˜๋ฉฐ, ์ด๋Š” ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Œ
    • ๊ฐ•์ œ์ ์ธ ๋งŒ๋ฃŒ ์ฒ˜๋ฆฌ ์–ด๋ ค์›€

      • ์œ ํšจ๊ธฐ๊ฐ„์ด ๋‚จ์•„ ์žˆ๋Š” ์ •์ƒ์ ์ธ ํ† ํฐ์— ๋Œ€ํ•ด ๊ฐ•์ œ์ ์œผ๋กœ ๋งŒ๋ฃŒ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ธฐ ์–ด๋ ค์›€
      • ๋งŒ๋ฃŒ๋œ ํ† ํฐ์€ ๋” ์ด์ƒ ์œ ํšจํ•˜์ง€ ์•Š์ง€๋งŒ, ์œ ํšจ๊ธฐ๊ฐ„์ด ๋‚จ์€ ํ† ํฐ์€ ๊ณ„์† ์‚ฌ์šฉ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Œ
    • ์ƒํƒœ ๊ด€๋ฆฌ์˜ ์–ด๋ ค์›€

      • JWT๋Š” ์ƒํƒœ๋ฅผ ๋‚ด๋ถ€์— ํฌํ•จํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ† ํฐ ๋‚ด๋ถ€์˜ ์ •๋ณด๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ํ•ด๋‹น ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํšจ๊ณผ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ค์›€
      • ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ•ด๋‹น ์ •๋ณด๊ฐ€ ํ† ํฐ ๋‚ด๋ถ€์— ๋ฐ˜์˜๋˜์–ด์•ผ ํ•จ

REST API with JWT

gradle ์˜์กด์„ฑ ์ถ”๊ฐ€

yml ์„ค์ •

@Component
@ConfigurationProperties(prefix = "jwt")
@Data
public class JwtConfigure {

  private String header;

  private String issuer;

  private String clientSecret;

  private int expirySeconds;
}
  • ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ 1๋ถ„์œผ๋กœ ํ•˜๋Š” JWT ํ† ํฐ ์„ค์ •์„ ์ถ”๊ฐ€
    • header: HTTP Header ์ด๋ฆ„
    • issuer: ํ† ํฐ ๋ฐœ๊ธ‰์ž
    • client-secret: HS512 ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ์„œ๋ช…์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ‚ค ๊ธธ์ด๋ฅผ 64๋ฐ”์ดํŠธ๋กœ ํ•ด์•ผํ•จ
    • expiry-seconds: ํ† ํฐ ๋งŒ๋ฃŒ ์‹œ๊ฐ„ (์ดˆ)

Jwt ํด๋ž˜์Šค

public final class Jwt {

  private final String issuer;

  private final String clientSecret;

  private final int expirySeconds;

  private final Algorithm algorithm;

  private final JWTVerifier jwtVerifier;

  public Jwt(String issuer, String clientSecret, int expirySeconds) {
    this.issuer = issuer;
    this.clientSecret = clientSecret;
    this.expirySeconds = expirySeconds;
    this.algorithm = Algorithm.HMAC512(clientSecret);
    this.jwtVerifier = com.auth0.jwt.JWT.require(algorithm)
      .withIssuer(issuer)
      .build();
  }

	public String sign(Claims claims) {
    Date now = new Date();
    JWTCreator.Builder builder = com.auth0.jwt.JWT.create();
    builder.withIssuer(issuer);
    builder.withIssuedAt(now);
    if (expirySeconds > 0) {
      builder.withExpiresAt(new Date(now.getTime() + expirySeconds * 1000));
    }
    builder.withClaim("username", claims.username);
    builder.withArrayClaim("roles", claims.roles);
    return builder.sign(algorithm);
  }

  public Claims verify(String token) throws JWTVerificationException {
    return new Claims(jwtVerifier.verify(token));
  }

  // ... ์ƒ๋žต ...

	static public class Claims {/*์ƒ๋žต*/}
}
  • JWT ๋ฐœํ–‰์„ ์œ„ํ•œ sign ๋ฉ”์†Œ๋“œ
  • JWT ๊ฒ€์ฆ์„ ์œ„ํ•œ verify ๋ฉ”์†Œ๋“œ

JwtAuthenticationFilter

๊ตฌํ˜„

public class JwtAuthenticationFilter extends GenericFilterBean {

    private final Logger log = LoggerFactory.getLogger(getClass());

    private final String headerKey;

    private final Jwt jwt;

    public JwtAuthenticationFilter(String headerKey, Jwt jwt) {
        this.headerKey = headerKey;
        this.jwt = jwt;
    }

    /**
     * HTTP ์š”์ฒญ ํ—ค๋”์— JWT ํ† ํฐ์ด ์žˆ๋Š”์ง€ ํ™•์ธ
     * JWT ํ† ํฐ์ด ์žˆ๋‹ค๋ฉด, ์ฃผ์–ด์ง„ ํ† ํฐ์„ ๋””์ฝ”๋”ฉ ํ•˜๊ณ ,
     * username, roles ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜๊ณ , UsernamePasswordAuthenticationToken ์ƒ์„ฑ
     * ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ UsernamePasswordAuthenticationToken ์ฐธ์กฐ๋ฅผ SecurityContext์— ๋„ฃ์–ด์คŒ
     */
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (SecurityContextHolder.getContext().getAuthentication() == null) {
            String token = getToken(request);
            if (token != null) {
                try {
                    Jwt.Claims claims = verify(token);
                    log.debug("Jwt parse result: {}", claims);

                    String username = claims.username;
                    List<GrantedAuthority> authorities = getAuthorities(claims);

                    if (isNotEmpty(username) && authorities.size() > 0) {
                        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, authorities);
                        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    }
                } catch (Exception e) {
                    log.warn("Jwt processing failed: {}", e.getMessage());
                }
            }
        } else {
            log.debug("SecurityContextHolder not populated with security token, as it already contained: '{}'", SecurityContextHolder.getContext().getAuthentication());
        }
        chain.doFilter(request, response);
    }

    private String getToken(HttpServletRequest request) {
        //์ƒ๋žต
    }

    private Jwt.Claims verify(String token) {
        return jwt.verify(token);
    }

    private List<GrantedAuthority> getAuthorities(Jwt.Claims claims) {
    	//์ƒ๋žต
    }
}
  • HTTP ์š”์ฒญ ํ—ค๋”์—์„œ JWT ํ† ํฐ์ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • JWT ํ† ํฐ์—์„œ loginId, roles์„ ์ถ”์ถœํ•˜์—ฌ UsernamePasswordAuthenticationToken์„ ์ƒ์„ฑ
  • ์•ž์„œ ๋งŒ๋“  UsernamePasswordAuthenticationToken๋ฅผ SecurityContext์— ๋„ฃ์–ด์คŒ

์œ„์น˜ ์„ค์ •

@Configuration
public class WebSecurityConfigure {
	
	private final JwtConfigure jwtConfigure;

	@Bean
    public Jwt jwt() {
    	return new Jwt(
        	jwtConfigure.getIssuer(),
            jwtConfigure.getClientSecret(),
            jwtConfigure.getExpirySeconds()
        );
    }

	public JwtAuthenticationFilter jwtAuthenticationFilter(Jwt jwt) {
        return new JwtAuthenticationFilter(
        	this.jwtConfigure.getHeader(),
            jwt
        );
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
  		http
        /**
         * Jwt ํ•„ํ„ฐ ์ถ”๊ฐ€
         */
        .addFilterAfter(jwtAuthenticationFilter(jwt), SecurityContextHolderFilter.class)
        .build();
    }
}
  • JWT ํ•„ํ„ฐ๋Š” Spring Security ํ•„ํ„ฐ ์ฒด์ธ์— ์ถ”๊ฐ€
  • SecurityContextHolderFilter ํ•„ํ„ฐ ๋ฐ”๋กœ ๋’ค์— ์„ค์ •
    • SecurityContextHolderFilter ํ•„ํ„ฐ ์•ž์— ์œ„์น˜ํ•˜๊ฒŒ ๋˜๋ฉด, SecurityContextHolderFilter ํ•„ํ„ฐ๊ฐ€ SecurityContext๋ฅผ ๋ฎ์–ด ์จ๋ฒ„๋ฆผ
profile
์›น ๊ฐœ๋ฐœ์— ๊ด€์‹ฌ ์žˆ์Šต๋‹ˆ๋‹ค.

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

comment-user-thumbnail
2023๋…„ 8์›” 12์ผ

๋งŽ์€ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค, ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ