[8/10 TIL] SPRING SECURITY(Jwt ์ „์šฉ Authentication ์ถ”๊ฐ€)

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

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

Jwt ์ „์šฉ Authentication ์ถ”๊ฐ€

public class JwtAuthenticationToken extends AbstractAuthenticationToken {

  private final Object principal;

  private String credentials;

  public JwtAuthenticationToken(String principal, String credentials) {
    super(null);
    super.setAuthenticated(false);

    this.principal = principal;
    this.credentials = credentials;
  }

  JwtAuthenticationToken(Object principal, String credentials, Collection<? extends GrantedAuthority> authorities) {
    super(authorities);
    super.setAuthenticated(true);

    this.principal = principal;
    this.credentials = credentials;
  }

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

}
  • ์ง€๊ธˆ๊นŒ์ง€ Authentication ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ฒด๋กœ Spring Security์—์„œ ๊ธฐ๋ณธ ์ œ๊ณตํ•˜๋Š” UsernamePasswordAuthenticationToken์„ ์‚ฌ์šฉํ•จ
  • ์ง€๊ธˆ๋ถ€ํ„ฐ JWT ์ธ์ฆ ์ฒ˜๋ฆฌ๋ผ๋Š” ๊ฒƒ์„ ๋ช…ํ™•ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด Authentication ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ฒด๋กœ JwtAuthenticationToken ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•จ
    • ๋”์ด์ƒ UsernamePasswordAuthenticationToken ์‚ฌ์šฉ ์•ˆํ•จ

public class JwtAuthentication {

  public final String token;

  public final String username;

  JwtAuthentication(String token, String username) {
    checkArgument(isNotEmpty(token), "token must be provided.");
    checkArgument(isNotEmpty(username), "username must be provided.");

    this.token = token;
    this.username = username;
  }

  @Override
  public String toString() {
    return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
      .append("token", token)
      .append("username", username)
      .toString();
  }

}
  • ๋˜ํ•œ, ๊ธฐ์กด UsernamePasswordAuthenticationToken ํด๋ž˜์Šค์—์„œ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ principal ํƒ€์ž…์œผ๋กœ org.springframework.security.core.userdetails.User ํƒ€์ž…์ด ์‚ฌ์šฉ
  • ํ•˜์ง€๋งŒ ์ด์ œ๋ถ€ํ„ฐ JwtAuthenticationToken์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ principal ํƒ€์ž…์— JwtAuthentication ํƒ€์ž…์„ ์ง์ ‘ ๋งŒ๋“ค์–ด์„œ ๋” ์•Œ๋งž๊ฒŒ ์‚ฌ์šฉ

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 ํ† ํฐ์ด ์žˆ๋‹ค๋ฉด, ์ฃผ์–ด์ง„ ํ† ํฐ์„ ๋””์ฝ”๋”ฉ ํ•˜๊ณ ,
     * UsernamePasswordAuthenticationToken ๋Œ€์ฒดํ•ด์„œ, JwtAuthenticationToken ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
     */
    @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) {
                        JwtAuthenticationToken authentication =
                                new JwtAuthenticationToken(new JwtAuthentication(token, 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 Jwt.Claims verify(String token) {
        return jwt.verify(token);
    }

    private List<GrantedAuthority> getAuthorities(Jwt.Claims claims) {
    	//์ƒ๋žต
    }
}
  • JWT ํ† ํฐ์„ ๊ฒ€์ฆํ•˜๊ณ , ๋””์ฝ”๋”ฉํ•œ ๋‹ค์Œ JwtAuthenticationToken ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
  • JwtAuthenticationToken ์ƒ์„ฑ์ž์˜ ๋งค๊ฐœ๋ณ€์ˆ˜
    • principal ํ•„๋“œ: JwtAuthentication ๊ฐ์ฒด
    • details ํ•„๋“œ: ํด๋ผ์ด์–ธํŠธ IP ์ •๋ณด๋ฅผ ์ง€๋‹Œ, WebAuthenticationDetails ๊ฐ์ฒด
  • SecurityContextHolder.getContext().setAuthentication ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด JwtAuthenticationToken ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ์ „๋‹ฌํ•จ
profile
์›น ๊ฐœ๋ฐœ์— ๊ด€์‹ฌ ์žˆ์Šต๋‹ˆ๋‹ค.
post-custom-banner

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