Restful API 구현을 위한 Spring Security 설정해보기 #0 (스펙정의, 사전 작업 등)
- 웹 개발/Spring Framework
- 2020. 8. 14. 10:58
안녕하세요.
오늘은 스프링 프로젝트들 중에서 단연 최고 난이도로 알려져 있는 Spring Security 설정해보기 시리즈 중 첫번째 단계인 스펙정의 및 사전작업에 대해서 설명해드리고자 합니다.
제목부터 확인해볼까요?
Restful API 구현을 위한 Spring Security 설정해보기
1. Session Stateless
Restful API 라는 것은 여러가지 의미가 담겨있습니다. API URL에 대한 내용이 있을 수 있고, Session Stateless 라는 개념이 있을 수도 있고, Spring Hateoas와 관련된 link 기능을 제공하는 것과 관련이 있습니다.
이러한 여러가지 중에서 Spring Security에서 담당해야할 부분은 인증과 권한, 이 두 개념과 관련이 있는 Session Stateless라는 개념을 활용해볼 생각입니다.
API 서버는 유저의 세션을 관리하는 것이 아닌 특정 토큰에 의해서 요청 Request 헤더에 특정 토큰(주로 Access Token 이라 지칭)을 보내주면 인증이 완료되고 api 기능을 사용할 권한을 갖게 됩니다.
시큐리티 관련 포스팅을 같이 실습하며 따라오신다면 해당 개념에 대해서 확인해보실 수 있습니다.
2. Cors(Cross-Origin Resource Sharing) 교차 출처 자원 공유
보통 별도의 API 서버가 존재한다면 앱 어플리케이션인 SPA 프레임워크(react, vue, angular 등)를 사용하게 될텐데요. 이때 스프링 프로젝트와는 다른포트를 사용할 것입니다. 혹은 다른 서버(물리)일 수 있구요.
이런 경우 출처가 다르다고 판단하여 자원 공유를 정책적으로 금지한게 cors이슈입니다. 이는 스프링 시큐리티에서 특정 도메인을 열어주거나 닫아줄 수 있습니다.
Cors 이슈에 관한 내용이 어떻게 처리되는지 확인해보실 수 있을 것입니다. Cors 처리는 여러가지 방법으로 처리가 가능합니다. 필터를 통한 처리, mvc 설정으로 처리할 수도 있습니다.
이러한 이슈를 처리하는 도중에 브라우저에서 요청을 보내는 preflight에 대해서 스프링 시큐리티에서 어떻게 처리할 수 있는지를 해볼 것입니다.
사전 작업
참고로 데이터베이스는 활용하지 않을 것입니다. 인증과 권한이 일어난 후의 일은 서비스나 데이터베이스에서 일어나는 일이나 스프링 시큐리티에서는 관리해줘야할 영역 밖이기 때문에 이는 스프링 개발을 어느정도 해보셨다면 실전 프로젝트를 진행해보실때 충분히 살을 붙여서 진행하실 수 있을 것입니다.
1. 프로젝트 생성
스프링 부트 프로젝트를 생성해줍니다. 스프링 부트는 Spring Starter 프로젝트로 STS나 IntelliJ 유료 버전에서 생성할 수 있습니다. 또한, 여기에서 생성하실 수 있습니다.
의존성으로는 반드시 Spring Web, Validation(2.3이후 버전일때), Spring Security, Lombok 이 네개 정도는 넣어주세요. 포스팅을 하면서 계속해서 pom.xml을 올리겠습니다.
생성을 하셨다면 프로젝트가 잘 실행되는지 확인해줍니다. -> main 메소드 실행 -> Started 로그 확인
2. Controller, Service 클래스 생성
Controller, Service 패턴은 스프링 개발하시는 분들에게는 가장 기본적인 의존패턴이기 때문에 이전에 개발하셨던 대로 추가하시면 될 것 같습니다.
하지만 Controller에서 URL을 구분지을 거에요!!
TestController.java
@RequiredArgsConstructor
@RequestMapping("/api/v1/test")
@RestController
public class TestController {
private final TestService testService;
@GetMapping("/permit-all")
public Object getTest() throws Exception {
return testService.getTest();
}
@GetMapping("/auth")
public Object getTest2() throws Exception {
return testService.getTest2();
}
}
결과는 같은 "test" 문자열을 리턴하는 API 입니다. 차이는 인증을 거치느냐 안거치느냐입니다.
/permit-all 을 가지는 api는 인증을 거치치 않고 모두에게 공개되는 api 입니다.
/auth 을 가지는 api는 인증을 거치고 사용할 수 있는 api 입니다.
이렇듯 두가지 Controller requestMapping을 정의 해주시기 바랍니다.
사전 작업 및 스펙정의는 이정도에서 마무리 지을 수 있을 것 같습니다. 포스팅을 진행하면서 추가되는 부분은 그때그때 게시물에서 확인할 수 있도록 변경내역을 안내해드릴 수 있도록 하겠습니다.