대빵's Blog

Spring Security + Angular 6 설정하기 본문

개발관련

Spring Security + Angular 6 설정하기

bigzero 2018. 9. 26. 13:25
일단 Spring Security 를 설정하려면 Spring Security 가 제공하는 기능이 왜 필요한지 이해하고 있어야 한다.

* CSRF (Cross-site Request Forgery : 사이트 간 요청 위조)
일단 사용자는 정상적인 방법으로 해당 사이트에 로그인 또는 인증받은 상태이다. 
이 상태에서 사용자가 어떤 게시물을 클릭하는 경우 해당 게시물에 악성코드가 삽입되어 있다면 해당 사용자는 본인도 모르게 이 코드를 실행하여 해당 사이트를 공격하게 된다.
예를 들어 게시물에 "<img src= "https://travel.service.com/travel_update?.src=Korea&.dst=Hell">" 이러한 이미지 태그가 존재하는 경우 사용자는 해당 코드를 실행하게 된다.
즉, CSRF를 방어하기 위해서는 개발자가 개발해서 배포한 실행코드 이외의 코드에 대해서 방어해야 한다.

Spring Security는 기본적으로 서버에서 토큰을 생성하여 내려주고 해당 토큰을 개발자가 코딩하여 서버로 다시 전송함으로서 개발자가 코딩하지 않은 코드의 실행을 방어한다.

  1. 사용자가 최초 사이트에 접속
  2. Spring Security 에서 사용자의 Response 에 token 을 붙여서 내려줌( Response Cookie 설정)
  3. 개발자는 모든 서버로 전송하는 코드에 (Form submit , REST 등) 해당 쿠키를 읽어서 request header 또는 input parameter 에 해당 쿠키의 token 값을 전송함.(xsrf-token 이 key 임)
  4. 이 때 쿠키값이 서버로 같이 전송됨
  5. Spring Security 는 개발자가 전송한 token 값(header 또는 request parameter) 과 쿠키의 token 값이 동일한 지 확인함으로서 해당 실행코드가 개발자의 코딩에 의해서 구현된 코드임을 확인함.
  6. 확인되면 해당 코드는 실행되고 서버는 다시 response cookie 에 token 값을 실어서 응답을 줌( header 에 넣는 경우 key는 X-XSRF-TOKEN 임, request param 인 경우 key 는 _csrf 임)
  7. response 에 받은 cookie 값은 다음 request 시 token 으로 사용됨( 2 ~ 6 반복 )

따라서 Angular 를 사용하는 경우 아래 두가지 작업을 해줘야 한다.
  1. REST API  request/response 에 cookie 를 사용 가능토록 설정해야 한다.
  2. 모든 REST API 호출에 해당 쿠키값을 읽어서 request header (또는 parameter value) 에 token 값을 삽입하는 작업을 해줘야 한다.
또한, angular cli 6.x 에서 proxy-config 를 사용하는 경우 이유는 알수 없지만 cookie 가 정상 작동하지 않았기 때문에 proxy-config 를 사용하지 않았다.

나의 경우 HttpInterceptor 를 구현하여 해당 작업을 처리했다.


일단 ngx-cookie-service 를 설치하여 cookie 를 읽을 수 있도록 했고,
request 를 clone 하여 header 에 cookie 값을 넣도록 하였다.
withCredentials 를 true 로 설정하여 cookie 값을 rest api 에서 사용가능토록 설정하였다.

* CORS ( Cross Origin Resource Sharing )
쉽게 얘기하면 Resource를 다른 서버와 공유할 수 있도록 해주는 설정이다.
Resource 는 딱히 정해진것은 없고 이미지가 될 수도 있고 REST API 가 될 수도 있다.
최근 웹 환경에서 Client Code 들은 HTML 에 존재한다. 과거 JSP 가 대세였던 시절 JSP 를 Application Server(WAS) 에서 html 로 변환되어야만 사용자에게 html 로 서비스 가능했기 때문에 별도의 웹서버는 CDN이나 proxy 이외에 크게 역할이 중요하지는 않았었다. 
그러나 최근 UI 환경은 javascript 에 의한 UI 구현이 대세가 되고 서버는 REST API 에 의한 데이터의 처리만 작동하므로서 웹서버에 사용자가 실행하는 코드가 운영되고 WAS에 REST API 가 운영되는 형태를 가진다.
이러한 환경에서 사용자가 처음 접속한 코드는 A 라는 웹서버에서 구동되고 REST API 는 B 라는 WAS에서 운영되므로 A 와 B는 상호간에 신뢰할 수 있는 환경이 만들어져야 만 한다. 

Spring Security 의 CORS 설정을 하면 http request 의 origin 서버 URL 을 체크하여 해당 서버가 인증된 서버임을 체크한다.
아래의 나의 경우 설정한 샘플 코드 이다.


CSRF 설정 밑에 CORS 설정을 추가했다.

CORS 설정에서 locahost:4200 을 Origin 으로 설정하여 Angular cli 환경의 웹서버를 인증한다.
그외에 header 에 개발자가 정한 규칙만 가능토록 필요시 설정한다. 
나의 경우 CORS 설정에서 X-Requested-With 의 header를 추가했기 때문에 위의 angular CSRF 설정에 추가로 X-Requested-With header를 나중에 추가했다.


여기까지 설정하면 Spring Security 환경에서 Angular 와 통신하기 위한 기본적인 보안설정이 완료된 상황이다.

다른 대부분의 사이트 글에서 csrf.disable() 하던지 cors 에서 allow all(Arrays.asList("*") ) 이런 식으로 CSRF 와 CORS 설정을 사용불가 시키고 작업을 진행하라는 식으로 되어 있는데 이렇게 하면 보안이 취약하여 차후 개발이 완료된 이후 보안취약점이 발생하여 많은 코드들을 재구현 해야 될 수 있다. 
초기에 적절한 설정을 통하여 미리 불필요한 재작업이 발생하지 않도록 하는 것을 권장한다.