
java
@FeignClient(name = "authAdaptor", url = "${api.blog.url}", path = "/api/auth")
public interface AuthAdaptor {
@PostMapping("/login")
ResponseEntity<String> login(@RequestBody Map<String, String> loginRequest);
}
@Controller
public class AuthController {
// Spring이 자동으로 만든 구현체를 여기에 넣어줌
private final AuthAdaptor authAdaptor;
@PostMapping("/api/auth/login")
public String login(...) {
// 사용자가 입력한 이메일과 비밀번호를 Map에 담기
Map<String, String> requestBody = new HashMap<>();
requestBody.put("email", email);
requestBody.put("password", password);
// 백엔드 API 호출하기 !!🌟
ResponseEntity<String> responseEntity = authAdaptor.login(requestBody);
// 응답 처리하기
// ...
}
}
POST /api/auth/login HTTP/1.1
Host: api.blog.url
Content-Type: application/json
{
"email": "user@example.com",
"password": "userPassword123"
}
HTTP/1.1 200 OK
Content-Type: text/plain
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.Map;
@FeignClient(name = "authAdaptor", url = "${api.blog.url", path = "/api/auth")
public interface AuthAdaptor {
// "/api/auth/login" 경로로 POST 요청을 보내는 메서드 선언
@PostMapping("/login")
ResponseEntity<String> login(@RequestBody Map<String, String> loginRequest);
}
Feign Client 선언: 백엔드 API와 통신하기 위한 인터페이스
name은 스프링에서 빈으로 등록할 때 사용
url : 요청을 보낼 서버의 기본 url(application.properties)
path : API 기본 경로
요청 본문에서 Map형태로 이메일 비밀번호를 담아서 전송
응답으로 JWT 토큰을 받음
@Controller
@RequiredArgsConstructor
public class AuthController {
private final AuthAdaptor authAdaptor;
@PostMapping("/api/auth/login")
public String login(@RequestParam String email, @RequestParam String password,
HttpServletResponse response, RedirectAttributes redirectAttributes){
}
}
// 응답 본문에서 JWT 토큰을 추출
String token = responseEntity.getBody();
HTTP/1.1 200 OK
Content-Type: text/plain
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGV4YW1wbGUuY29tIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
이렇게 온다면 getBody는
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGV4YW1wbGUuY29tIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
반환 하는데 이것이 JWT 토큰
메소드가 해야하는 역할
1. /api/auth/login 경로로 POST 요청이 도착
2. @RequestParam으로 이메일과 비밀번호를 받음
3. 이메일과 비밀번호를 Map에 담아 JSON 형태로 변환
// 백엔드 API에 보낼 JSON 데이터를 준비 (이메일과 비밀번호)
Map<String, String> requestBody = new HashMap<>();
requestBody.put("email", email);
requestBody.put("password", password);
ResponseEntity<String> responseEntity = authAdaptor.login(requestBody);
백엔드 API에서 인증 처리 (이메일, 비밀번호 검증 후 성공시 JWT 토큰 생성 후 응답)
응답 코드가 200인지, 응답 본문에서 JWT 토큰 추출
if(responseEntity.getStatusCode().is2xxSuccessful(){
// 응답 본문에서 토큰 추출
String token = responseEntity.getBody();
// jwtToken 이라는 이름의 쿠키 생성
Cookie cookie = new Cookie("jwtToken", token);
// 쿠키 경로 "/"로 설정(모든 페이지에서 사용이 가능하게)
cookie.setPath("/");
// 자바스크립트에서 쿠키 접근 할 수 없게 설정(XSS 공격방지)
cookie.setHttpOnly(true);
// 7. 쿠키를 HTTP 응답에 추가
response.addCookie(cookie);
}
// 홈페이지로 리다이렉트
return "redirect:/";
}else{
// 로그인 실패시 로그인 페이지로 리다이렉트
redirectAttributes.addAttribute("error", "true");
return "redirect:/login";
}
}catch(Exception e){
redirectAttributes.addAttribute("error", "true");
return "redirect:/login";
}
@GetMapping("/logout")
public String logout(HttpServletResponse response){
//JWT 토큰 쿠키 삭제
Cookie cookie = new Cookie("jwtToken", null);
cookie.setPath("/");
cookie.setMaxAge(0);
response.addCookie(cookie);
return "redirect:/login?logout=true";
}
