[java] Java JHipster의 JWT 인증 기능

Java JHipster는 자바 기반의 웹 애플리케이션을 빠르게 개발할 수 있는 프레임워크입니다. 이 프레임워크는 JWT(Jason Web Token) 인증 기능을 제공하여 보안적인 요구사항을 충족시킬 수 있습니다.

JWT란?

JWT는 인증과 정보 전달을 위해 사용되는 토큰 기반의 인증 방식입니다. 이 토큰은 JSON 형태로 인코딩되어 있으며, 클라이언트-서버 간의 안전한 통신을 위해 사용됩니다. JWT는 클라이언트가 서버에 인증 요청을 보내면 서버는 JWT를 발급하여 클라이언트에게 전달하고, 클라이언트는 이 JWT를 이용하여 서버에 대한 인증을 수행합니다.

JHipster와 JWT 인증

JHipster는 기본적으로 Spring Security를 사용하여 인증 및 권한 관리를 처리합니다. JWT 인증 기능은 Spring Security와 함께 사용되어 서버와 클라이언트 간의 인증을 처리합니다.

설정

JHipster 프로젝트에서 JWT 인증을 사용하려면 다음과 같은 설정이 필요합니다.

  1. SecurityConfiguration.java 파일에 JWT 인증을 활성화하는 설정을 추가해야 합니다. 아래는 예시 코드입니다.
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public TokenProvider tokenProvider() {
        return new TokenProvider();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
            .disable()
            .headers()
            .frameOptions()
            .disable()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers("/api/authenticate").permitAll()
            .antMatchers("/api/**").authenticated()
            .and()
            .apply(securityConfigurerAdapter());
    }

    private JWTConfigurer securityConfigurerAdapter() {
        return new JWTConfigurer(tokenProvider());
    }
}
  1. JWT 인증을 위한 필터를 설정합니다. JWTFilter.java 파일을 생성하여 아래의 코드를 추가합니다.
public class JWTFilter extends GenericFilterBean {

    private final TokenProvider tokenProvider;

    public JWTFilter(TokenProvider tokenProvider) {
        this.tokenProvider = tokenProvider;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String jwt = resolveToken(httpServletRequest);
        if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
            Authentication authentication = this.tokenProvider.getAuthentication(jwt);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        
        filterChain.doFilter(servletRequest, servletResponse);
    }

    private String resolveToken(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}
  1. JWT 인증을 위한 TokenProvider.java 파일을 생성하여 아래 코드를 추가합니다.
public class TokenProvider {

    private final String secretKey;
    private final long tokenValidityInMilliseconds;

    public TokenProvider() {
        // Secret key와 토큰의 유효 시간 설정
        this.secretKey = "yourSecretKey";
        this.tokenValidityInMilliseconds = 86400000L; // 24시간
    }

    public String createToken(Authentication authentication) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + this.tokenValidityInMilliseconds);

        return Jwts.builder()
            .setSubject(authentication.getName())
            .setIssuedAt(now)
            .setExpiration(expiryDate)
            .signWith(SignatureAlgorithm.HS512, secretKey)
            .compact();
    }

    public Authentication getAuthentication(String token) {
        Claims claims = Jwts.parser()
            .setSigningKey(secretKey)
            .parseClaimsJws(token)
            .getBody();

        Collection<? extends GrantedAuthority> authorities =
            Arrays.stream(claims.get("roles").toString().split(","))
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());

        User principal = new User(claims.getSubject(), "", authorities);

        return new UsernamePasswordAuthenticationToken(principal, token, authorities);
    }

    public boolean validateToken(String token) {
        try {
            Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
            return !claims.getBody().getExpiration().before(new Date());
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }
}

사용

JWT 인증을 사용하려면 클라이언트의 요청에 JWT 토큰이 포함되어야 합니다. api/authenticate 엔드포인트를 통해 로그인 시 JWT 토큰을 발급받을 수 있습니다. 발급된 토큰은 클라이언트가 서버에 요청을 보낼 때 Authorization 헤더에 포함시켜야 합니다.

아래는 JWT 토큰을 포함하여 보호된 리소스에 접근하는 예시입니다.

public ResponseEntity<String> getResource(@RequestHeader("Authorization") String token) {
    // 토큰을 이용하여 인증 처리
    // ...
    return ResponseEntity.ok("Resource accessed successfully");
}

위의 예시에서 @RequestHeader 어노테이션을 사용하여 요청 헤더에서 Authorization 값을 추출하여 토큰 값을 가져옵니다. 이 토큰 값은 인증을 위해 사용됩니다.

이와 같이 JHipster에서 JWT 인증을 설정하고 사용하여 안전한 웹 애플리케이션을 개발할 수 있습니다.

결론

Java JHipster의 JWT 인증 기능을 활용하면 자바 기반의 웹 애플리케이션을 보다 안전하게 개발할 수 있습니다. JWT를 사용하여 클라이언트-서버 간의 안전한 인증을 수행할 수 있으며, JHipster의 설정과 필터를 통해 이를 구현할 수 있습니다.