레스토랑 예약 사이트 만들기 13 - 인가
JWT로부터 데이터 가져오기public class JwtUtil { private Key key; public JwtUtil(String secret) { this.key = Keys.hmacShaKeyFor(secret.getBytes()); } public String createToken(Long userId, String name) { String token = Jwts.builder() .claim("userId", 1004L) .claim("name", name) .signWith(key, SignatureAlgorithm.HS256) .compact(); return token; } public Claims getClaims(String token){ Claims claims = Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody(); return claims; }} @Test@DisplayName("Claims를 가져온다.")public void getClaims(){ String token = "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEwMDQsIm5hbWUiOiJUZXN0ZXIifQ.I4DNdunio2m54tfUEaXHC_E-gvCQo6ZhHO15Ewkat6U"; Claims claims = jwtUtil.getClaims(token); assertThat(claims.get("userId", Long.class)).isEqualTo(1004L); assertThat(claims.get("name")).isEqualTo("Tester");} JWTFilter추가@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Value("${jwt.secret}") private String secret; @Override protected void configure(HttpSecurity http) throws Exception { Filter filter = new JwtAuthenticationFilter(authenticationManager(), jwtUtil()); http .cors().disable() .csrf().disable() .formLogin().disable() .headers().frameOptions().disable(); http .addFilter(filter) .sessionManagement() // Session을 사용하지 않음 .sessionCreationPolicy(SessionCreationPolicy.STATELESS); ; } @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } @Bean public JwtUtil jwtUtil(){ return new JwtUtil(secret); }} JWT 인증 Filterpublic class JwtAuthenticationFilter extends BasicAuthenticationFilter { private JwtUtil jwtUtil; public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtUtil jwtUtil) { super(authenticationManager); this.jwtUtil = jwtUtil; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { Authentication authentication = getAuthentication(request); if(authentication != null){ SecurityContext context = SecurityContextHolder.getContext(); context.setAuthentication(authentication); } chain.doFilter(request, response); } private Authentication getAuthentication(HttpServletRequest request){ // Header에서 Data를 얻어야 한다. String token = request.getHeader("Authorization"); if(token == null){ return null; } Claims claims = jwtUtil.getClaims(token.substring("Bearer ".length())); Authentication authentication = new UsernamePasswordAuthenticationToken(claims, null); return authentication; }} 요청시 Token값을 가지고 있는지 확인@RestController@RequiredArgsConstructorpublic class ReviewController { private final ReviewService reviewService; @PostMapping("/restaurants/{restaurantId}/reviews") public ResponseEntity<?> create( Authentication authentication, @PathVariable Long restaurantId, @Valid @RequestBody Review resource ) throws URISyntaxException { Claims claims = (Claims) authentication.getPrincipal(); String name = claims.get("name", String.class); Review review = reviewService.addReview(restaurantId, resource); String url = "/restaurants/" + restaurantId + "/reviews/" + review.getId(); return ResponseEntity.created(new URI (url)).body("{}"); }}