반응형

 


 [ REST API 제대로 알고 사용하기 ]

 어느 날 뜬금없이 대학교 친구에게 전화가 왔습니다. 그러더니 ‘야, REST API가 정확히 뭐 어떤 거야?’ 하는 질문에 가슴에 비수가 날아와 꽂힌 듯한 느낌을 받았습니다 . 며칠 전 카톡으로 요즘 보통 웹서비스들은 ‘REST API형태로 서비스를 제공한다’고 아는 척을 조금 했던 기억이 머릿속을 빠르게 스쳐 지나갔고 그 순간 대충 얼버무리며 ‘아, 그거 REST하게 클라이언트랑 서버간에 데이터를 주고 받는 방식'을 말한다며 얼렁뚱땅 마무리 지었던 기억이 납니다.  실제로 REST API의 서비스를 직접 개발도 해보고 사용도 해봤는데도 막상 설명을 하자니 어려움을 겪었던 적이 있으셨을텐데요. 그래서 이번에 REST API에 대해 정리하게 되었습니다. 기본적인 REST API에 대한 내용 외에도 REST API를 설계하실 때 참고해야 할 몇 가지 TIP들에 대해 공유해보도록 하겠습니다. 


1. REST API의 탄생

   REST는 Representational State Transfer라는 용어의 약자로서 2000년도에 로이 필딩 (Roy Fielding)의 박사학위 논문에서 최초로 소개되었습니다. 로이 필딩은 HTTP의 주요 저자 중 한사람으로 그 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되어지지 못하는 모습에 안타까워하며 웹의 장점을 최대한 활용할 수 있는 아키텍쳐로써 REST를 발표했다고 합니다.


2. REST 구성

쉽게 말해 REST API는 다음의 구성으로 이루어져있습니다. 자세한 내용은 밑에서 설명하도록 하겠습니다.

자원(RESOURCE) - URI

행위(Verb) - HTTP METHOD

표현(Representations)


3. REST 의 특징

1) Uniform (유니폼 인터페이스) 

: Uniform Interface는 URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일을 말합니다.


2) Stateless (무상태성) 

: REST는 무상태성 성격을 갖는다. 다시 말해 작업을 위한 상태정보를 따로 저장하고 관리하지 않는다. 세션 정보나 쿠키정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 된다. 때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해진다.


3) Cacheable (캐시 가능) 

: REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용이 가능하다. 따라서 HTTP가 가진 캐싱 기능이 적용가능하다. HTTP 프로토콜 표준에서 사용하는 Last-Modifyed태그나 E-Tag를 이용하면 캐싱 구현이 가능하다.


4) Self-descriptiveness (자체 표현 구조) 

: REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해 할 수 있는 자체 표현 구조로 되어 있다는 것이다.


5) Client - Server 구조 

: REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을 직접 관리하는 구조로  각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어들게 된다.


6) 계층형 구조 

: REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 한다.



4. REST API 디자인 가이드

! REST API 설계시 가장 중요한 항목은 다음의 2가지로 요약할 수 있습니다.

첫 번째, URI는 정보의 자원을 표현해야 한다.

두 번째, 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현한다.

다른 건 다 잊어도 위 내용은 꼭 기억하시기 바랍니다.


4-1  REST API 중심 규칙

1) URI는 정보의 자원을 표현해야한다. (리소스명은 동사보다는 명사를 사용)

GET /members/delete/1

 

위와 같은 방식은 REST를 제대로 적용하지 않은 URI입니다. URI는 자원을 표현하는데 중점을 두어야 합니다. delete와 같은 행위에 대한 표현이 들어가서는 안됩니다.


2) 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE 등)로 표현

 위의 잘못 된 URI를 HTTP Method를 통해 수정해 보면

DELETE /members/1

로 수정할 수 있겠습니다. 회원정보를 가져올 때는 GET, 회원 추가시의 행위를 표현하고자 할 때는 POST METHOD를 사용하여 표현합니다.

 

회원정보를 가져오는 URI

GET /members/show/1     (x)

GET /members/1          (o) 

 

회원을 추가할 때

GET /members/insert/2 (x)  - GET 메서드는 리소스 생성에 맞지 않는다.

POST /members/2       (o)

 

**[참고]HTTP METHOD의 알맞은 역할 **

POST, GET, PUT, DELETE 이 4가지의 Method를 가지고 CRUD를 할 수 있다. 

| POST | POST를 통해 해당 URI를 요청하면 리소스를 생성합니다. |

| GET | GET를 통해 해당 리소스를 조회 합니다. 리소스를 조회하고 해당 도큐먼트에 대한 자세한 정보를 가져온다. |

| PUT | PUT를 통해 해당 리소스를 수정 합니다. |

| DELETE | DELETE를 통해 리소스를 삭제합니다. |

다음과 같은 식으로 URI는 자원을 표현하는데에 집중하고 행위에 대한 정의는 HTTP METHOD를 통해 하는 것이 REST한 API를 설게하는 중심 규칙입니다.



4-2 URI 설계시 주의할 점

1) 슬래시 구분자(/)는 계층 관계를 나타내는 데 사용

EX )  * http://restapi.example.com/houses/apartments

         * http://restapi.example.com/animals/mammals/whales


2) URI 마지막 문자로 슬래시(/)를 포함하지 않는다 

: URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 하며 URI가 다르다는 것은 리소스가 다르다는 것이고, 역으로 리소스가 다르면 URI도 달라저여한다. REST API는 분명한 URI를 만들어 통신을 해야하기 때문에 혼동을 주지 않도록 URI 경로의 마지막에는 /를 사용하지 않는다.

http://restapi.example.com/houses/apartments/ (X)

http://restapi.example.com/houses/apartments  (0)


3) 하이픈(-)은 URI 가독성을 높이는데 사용 

: URI를 쉽게 읽고 해석하기 위해, 불가피하게 긴 URI경로를 사용하게 된다면 하이픈을 사용해 가독성을 높일 수 있다.


4) 밑줄(_)은 URI에 사용하지 않는다. 

: 글꼴에 따라 다르긴 하지만 밑줄은 보기 어렵거나 밑줄 때문에 문자가 가려지기도 한다. 이런 문제를 피하기 위해 밑줄 대신 하이픈을 사용하자(가독성)


5) URI 경로에는 소문자가 적합하다. 

: URI 경로에 대문자 사용은 피하도록 하자. 대소문자에 따라 다른 리소스로 인식하게 된다. RFC 3986(URI 문법 형식)은 URI 스키마와 호스트를 제외하고는 대소문자를 구별하도록 규정하기 때문이지요.

(*RFC 3986 is the URI (Unified Resource Identifier) Syntax document)


6) 파일 확장자는 URI에 포함시키지 않는다.

http://restapi.example.com/members/soccer/345/photo.jpg (X)

REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI 안에 포함시키지 않는다. Accept header를 사용하도록 합시다.

GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg



4-3 리소스간의 관계를 표현하는 방법

: REST 리소스 간에는 연관 관계가 있을 수 있고 다음과 같은 표현방법으로 사용하자.

/리소스명/리소스 ID/관계가 있는 다른 리소스명

ex) GET : /users/{userid}/devices  (일반적으로 소유 ‘has’의 관계를 표현할 때)

만약에 관계명이 복잡하다면 이를 서브 리소스에 명시적으로 표현하는 방법이 있다. 예를 들어 사용자가 ‘좋아하는’ 디바이스 목록을 표현해야 할 경우 다음과 같은 형태로 사용될 수 있다.

GET : /users/{userid}/likes/devices (관계명이 애매하거나 구체적 표현이 필요할 때)



4-4 자원을 표현하는 Colllection과 Document

: Collection과 Document에 대해 알면 URI 설계가 한 층 더 쉬워집니다. DOCUMENT는 단순히 문서로 이해해도 되고, 한 객체라고 이해하셔도 될 것 같습니다. 컬렉션은 문서들의 집합, 객체들의 집합이라고 생각하시면 이해하시는데 좀 더 편하실 것 같습니다. 컬렉션과 도큐먼트는 모두 리소스라고 표현할 수 있으며 URI에 표현됩니다. 예를 살펴보시도록 하겠습니다.

http:// restapi.example.com/sports/soccer

위 URI를 보시면 sports라는 컬렉션과 soccer라는 도큐먼트로 표현되고 있다고 생각하시면 됩니다. 좀 더 예를 들어보자면

http:// restapi.example.com/sports/soccer/players/13

sports, players 컬렉션과 soccer, 13(13번인 선수)를 의미하는 도큐먼트로 URI가 이루어지게 됩니다. 여기서 중요한 점은 컬렉션은 복수로 사용하고 있다는 점입니다. 좀 더 직관적인 REST API를 위해서는 컬렉션과 도큐먼트를 사용하실 때 단수 복수도 지켜주신다면 좀 더 이해하기 쉬운 URI를 설계하실 수 있을 것 같습니다.
 


5. HTTP 응답 상태 코드

마지막으로 응답 상태코드를 간단히 살펴보도록 하겠습니다. 잘 설계된 REST API는 URI만 잘 설계된 것이 아닌 그 리소스에 대한 응답을 잘 내어주는 것 까지 포함되어야 합니다. 정확한 응답의 상태코드만으로도 많은 정보를 전달할 수가 있기 때문에 응답의 상태코드 값을 명확히 돌려주는 것은 생각보다 중요한 일이 될 수도 있습니다. 혹시 200이나 4XX관련 특정 코드 정도만 사용하고 계시다면 처리 상태에 대한 좀 더 명확한 상태코드 값을 사용하실 수 있기를 권장하는 바입니다.

상태코드에 대해서는 몇 가지지만 정리하도록 하겠습니다.



200 - 클라이언트의 요청을 정상적으로 수행함

201 - 클라이언트가 어떠한 리소스 생성을 요청, 해당 리소스가 성공적으로 생성됨(POST를 통한 리소스 생성 작업시)


400 - 클라이언트의 요청이 부적절 할 경우 사용하는 응답 코드

401 - 클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을때 사용하는 응답 코드 (로그인 하지 않은 유저가 로그인했을 때 요청 가능한 리소스를 요청했을 때)

403 - 유저 인증상태와 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 때 사용하는 응답 코드 (403 보다는 400이나 404를 사용할 것을 권고. 403자체가 리소스가 존재한다는 뜻이기 때문에)

405 - 클라이언트가 요청한 리소스에서는 사용 불가능한 Method를 이용했을 경우 사용하는 응답 코드


301 - 클라이언트가 요청한 리소스에 대한 URI가 변경 되었을때 사용하는 응답 코드 (응답시 Location header에 변경된 URI를 적어 줘야 한다.

500 - 서버에 문제가 있을 경우 사용하는 응답 코드


[ 글을 마치며 ]

그래서 'REST API가 정확히 뭐 어떤 거야?'라고 다시 묻는 다면 'HTTP METHOD와 자원을 표현하는 URI를 이용해 서비스의 데이터에 접근하는 것' 라고 제 나름의 정의를 내려보았습니다. 물론 비전공자인 친구에게는 추가적인 설명이 필요할 것 같습니다. 


RESTFul한 API를 설계하실 때 도움이 될 만한 내용들을 제 나름의 우선순위를 가지고 정리해 보았습니다. 정리를 하면서 다시 한 번 느낀 것은 정확히 알지 못하면 '설명할 수 없다'는 것입니다. 누군가가 그런 말을 하였습니다. '당신이 어떤 것을 할머니에게 설명해 주지 못한다면, 그것은 진정으로 이해한 것이 아니다.' 저 문구를 항상 가슴 깊이 새기고 앞으로 무엇인가 새로운 지식을 학습해 실무에 적용할 때에도 '대충'이 아닌 '정확한 이해'를 바탕으로 문제를 해결해 나가도록 해야겠다'는 다짐과 함께 글을 마무리 짓도록 하겠습니다.


마지막으로 REST API는 정해진 명확한 표준이 없기 때문에 REST API를 사용함에 있어 '무엇이 옳고 그른지'가 아닌 개발하는 서비스의 특징과 개발 집단의 환경과 성향 등이 충분히 고려되어 설계되어져야 할 것입니다

 

 

긴 글 읽어주셔서 감사합니다.


[ Reference ]

- 일관성 있는 웹 서비스 인터페이스 설계를 위한 REST API 디자인 규칙(한빛미디어)

https://ko.wikipedia.org/wiki/REST

http://blog.remotty.com/blog/2014/01/28/lets-study-rest/

https://yangbongsoo.gitbooks.io/study/content/restc758_c774_d574_c640_c124_acc4.html

http://spoqa.github.io/2012/02/27/rest-introduction.html


#NHN엔터테인먼트가 만드는 IT 서비스를 소개하고, 개발 경험을 공유하는 기술 커뮤니티 이고 해당 페이지에 게시한 글입니다.

많은 구독부탁드립니다:)

https://www.facebook.com/toast.nhnent/?fref=ts 


반응형
반응형



@QueryParam ? @PathParam?

흔히 API설계하실 때 특히 GET 방식의 URI 만드실 때 쿼리 파라미터로 설계할지 패스파라미터로 설계하실지 고민들하실텐데요.


저또한 많이 고민하다가 관련해서 열띤 토론?을 나눈 stackoverflow글이 있어 공유합니다.



---------------------------------------------------------------------------------------------------------------------------------------


This is what I do.

If there is a scenario to retrieve a record based on id, for example you need to get the details of the employee whose id is 15, then you can have resource with @PathParam.

GET /employee/{id}

If there is a scenario where you need to get the details of all employees but only 10 at a time, you may use query param

GET /employee?start=1&size=10

This says that starting employee id 1 get ten records.

To summarize, use @PathParam for retrieval based on id. 

User @QueryParam for filter or if you have any fixed list of options that user can pass.


[ 자세한건 참고 : StackOverflow]

http://stackoverflow.com/questions/11552248/when-to-use-queryparam-vs-pathparam

-------------------------------------------------------------------------------------------

[ 결 론 ]

결국에는 특정 정보를 가지고 올 때는  PATH PARAMETER를 데이터에 특정 조건(필터)를 주거나 SORT를 해서 가지고 오고자 할 경우에는 쿼리파라미터를 사용하면 좀 더 깔끔하게 API 를 설계하실 수 있을 것 같습니다.

감사합니다.

 




반응형
반응형



 안녕하세요. 오늘은 ENUM을 JSP에서 받아 사용하는 방법에 대해 포스팅하려고 합니다. 많은 분들이 공통적으로 자주 사용하는 코드 값들이나 타입들을 ENUM에 넣어서 주로 사용하실 텐데요. ENUM을 값 그대로 가져와서 JSP에서 쓸 수 있는 좋은 방법이 있어 포스팅을 하려고 합니다. 저 또한 최근에 ENUM값을 JSP에서 사용해야 하는 기능 개발 건이 있었는데 오늘 포스팅 하는 내용을 통해 쉽게 해결할 수 있었습니다.


먼저 ENUM을 어떻게 JSP에서 사용할 수 있었는지에 대해 간단한 절차를 적어보도록 하겠습니다.1. 사용하고자 하는 ENUM 클래스를 작성합니다.2. web.xml에 Context-param으로 해당 enum 클래스를 등록해 줍니다.3. EnumContextListner를 web.xml에 등록해 줍니다.4. EnumContextListner 클래스를 작성합니다.5. JSP에서 Context-param으로 등록한 ENUM을 가져다가 사용합니다.


1. 사용하고자하는 ENUM 클래스를 작성합니다.해당 내용은 포스팅을 위해 번호와 이메일을 임의로 작성하였습니다. 잘린 부분은 get,set메서드이기 때문에 생략하도록 하겠습니다.



2. web.xml에 Context-param으로 해당 enum 클래스를 등록해 줍니다.위에서 작성한 SmsServiceType 클래스를 Context-param의 param-value에 등록해 줍니다. 간단히 Context-param에 대해 설명하자면 보통 사용자의 요청(ex, www.nr.com/dongbeom)이 웹서버를 거쳐 웹 어플리케이션 서버(탐캣)에 들어왔을 경우 그에 해당하는 servlet을 생성하게 됩니다. Context-param은 사용자의 요청에 의해 생성되는 모든 servlet에서 Context-param으로등록 된 값을 사용할 수 있도록 하는 존재로 쉽게 전역 변수의 역할과 비슷하다고 생각하시면 될 것 같습니다.

밑의 그림에서는 Context-param의 이름이 enumServletContextConfig이고 com.nhncorp.echo.eme.model.SmsServiceType의 클래스를 값으로 가지고 있는 컨텍스트를 정의하고 있습니다.




3. EnumContextListner를 web.xml에 등록해 줍니다.
리스너는 컨텍스트에 정의되어 있는 것들을 모든 서블릿과 필터가 공유할 수 있도록 해줍니다.밑의 그림에서 EnumContextListener 클래스를 listener-class로 등록하고 있는 것을 볼 수 있습니다. 보통 컨텍스트의 값과 리스너들은 클라이언트에서 요청이 들어오지 않아도 web.xml이 읽혀질 때 호출되게 됩니다. (서버가 시작되는 시점에도 호출되게 됨)



4. EnumContextListner 클래스를 작성합니다.해당 클래스에 대해 간단히 설명하자면 web.xml에서 등록한 Context-param의 값들을 다 가져와서 MAP과 LIST로 만들어 JSP에서 사용할 수 있도록 ServletContext에 set을 해주는 역할을 합니다. 또한 loadEnum이라는 메소드를 보시면 ENUM 을 맵과 리스트로 만들어 Collections.unmodifiableMap, Collections.unmodifiableList로 변환해 read-only MAP과 LIST로 변경해 주는 작업도 진행 합니다. (혹시나 ENUM 값을 다른 곳에서 초기화하거나 값을 변경하는 불상사를 막을 수 있음)





5. JSP에서 Context-param으로 등록한 ENUM을 가져다가 사용합니다.

위와 같은 과정을 거치면 모든 JSP에서 해당 ENUM 값을 가져다가 사용할 수 있습니다. 사용하는 방

법에 대한 가이드를 참고 하셔서 사용하시면 됩니다.

[ 참고 가이드 ] 
1) web.xml에 리스너 등록 
2) web.xml의 context-param으로 enumServletContextConfig를 등록. value값에 사용할 enum클래스명을 기입 
3) jsp에서 등록한 enum을 ${enum명(소문자시작)} 형식으로 호출할 수 있다. ex) ${day.MONDAY} 
4) enum.values()의 경우 ${enum명 + List} 형식으로 호출할 수 있다. ex) ${dayList}


저 같은 경우에는 list형태로 다음과 같이 사용하였습니다. ${smsServiceTypeList}


포스팅은 여기서 마치고 이번 포스팅을 진행하다보니 이번 포스팅을 이해하기 위해 필요한 기본적인 내용들에 대해서(web.xml, servletContext.xml, applicationContext.xml 등등)는 아직 포스팅이 많이 안된 것 같은데 시간 나는 대로 다시 한 번 개념을 정리할 겸 포스팅하도록 하겠습니다.


감사합니다.





반응형
반응형

 


 안녕하세요 이번 포스팅에서는 Xss Filter에 대한 간단한 개념과 이번에 작업을 하다가 헤맸던 JSP에서 폼의 타입이 enctype ="multipart/form-data"일 때 XSS FILTER가 적용되지 않았던 문제에 대해 알아보고자 합니다. Xss Filter를 기존에 써봤다는 가정 하에 포스팅을 진행하겠습니다. ( 기본적인 XSS Filter를 적용하는 법에 대한 설명은 포함되어 있지 않음을 미리 말씀드립니다. )



 ▶ XSS Filter란???


 Xss Filter란 사용자들의 악의적인 스크립트 공격(ex, <script> alert("melong"); </script> )등을 막기 위해 사용하는 filter로 안정적인 웹서비스를 위해서는 필수적인 요소입니다. XSS는 Cross-Site Scripting를 의미한다. 보통 해당 filter를 사용하기 위해서는 web.xml에 필터를 정의해주고 거기에 해당하는 url을 매핑해주고 filter 클래스를 작성해주면 된다.( 이에 대한 내용은 생략합니다.) 



 ▶ 작업 중 문제 발생 ( JSP에서 form의 타입이 enctype="multipart/form-data"일 경우 XSS Filter를 타지 못함)


 보안팀으로부터 페이코 앱 고객센터의 문의를 넣는 페이지에 xss filter가 적용되어 있지 않아 보안에 취약하다는 메일을 한 통 받았습니다. 메일을 받고 가장 먼저 확인한 것은 "web.xml에 해당 문의를 넣을 때의 url이 XSS Filter url에 매핑이 되어있는가" 였습니다. 이를 확인한 결과 해당 url이 XSS Filter에 잘 매핑되어 있는 것을 확인 할 수 있었습니다. 여기서 되게 의아했습니다. 그래서 제가 직접 페이코 앱에서 스크립트( <script> alert("N"); </script> )를 제목 부분에 넣어 문의를 넣어 보았습니다.




 1:1 문의에 들어가서 문의를 넣고 내 문의 보기를 누르자 alert창이 뜨는 것을 볼 수 있었습니다. 도대체 왜 xss filter에 매핑이 되어 있는데 해당 스크립트의 내용이 안 걸러지는지 의아했습니다. 

                                                                           


 


 그림(보안상의 이슈로 모자이크 처리)을 보면 아시겠지만 /~/app/mail/addInquiry.nhn이 문의를 넣을 때 요청되는 url이고 잘 mapping되어 있는 것을 확인하실 수 있습니다. 잘 매핑은 되어 있는데 왜 필터링이 안될까하는 의문과 함께 filter와 wrapper클래스를 디버깅해 본 결과 폼에 의해 전송되는 값들을 제대로 호출해오지 못하는 점을 발견 하였습니다. 그래서 검색을 해본 결과 

 


 그림에서 보는 것과 같이 form 타입을 multipart/form-data로 폼을 넘길 경우 xss filter에서 해당 폼의 request의 값들을 제대로 읽어오지 못하는 것을 알 수 있었습니다. 해당 페이지가 기본적인 제목, 내용을 입력 받고 첨부파일 기능 또한 있는 페이지 이기 때문에 폼의 타입이 multipart/form-data일 수 밖에 없었습니다. 따라서 해당 타입으로 폼이 전송될 때 파일첨부 이외의 값들에 대해 XSS Filter를 통해 스크립트와 악의적인 공격들을 막아주어야하는데 XSS Filter가 폼의 값들을 제대로 읽어들이지 못하고 있었습니다. 문제는 multipart/form-data형식의 경우에는 파라미터를 읽을 때 getPart()와 getParts()라는 메소드를 사용하는데 해당 사용하고 있는 filter 클래스를 보면  getParameter와 getParameterValues()로 요청으로 부터 넘어온 값들에 대해 filter를 적용하는 것을 확인할 수 있었습니다. (밑의 그림)



 ▶ 문제 해결 방법


 위와 같이 form의 타입이 enctype="multipart/form-data"일 경우 XSS Fitler를 타지 못하는 문제를 해결 하기 위해서 XSS Filter 전에 "MultipartFilter"를 적용해 주어 먼저 multipartFile에 대해 필터를 적용해 주고 XSS Filter를 타게 해주어야 합니다. 


 


 그림(혹시나 해서 특정 부분은 모자이크 처리)과 같이 XSS 필터 위에 multipartFilter를 적용한 것을 보실 수 있습니다. 여기서 주의 사항은 multipartFilter에 url에 매핑을 시켜줬다고 해서 XSS Filter에서 url을 제거하면 안됩니다. ( 두 필터 모두에 url이 매핑되어 있어야함!!!! 저는 mutipartFilter에 매핑시켜줬으니까 xss에는 안해도 되나하고 안했다가 많은 시간을 낭비했다는 ㅠ,ㅠ) 이로 인해 form의 타입이 enctype="multipart/form-data"여도 XSS Filter가 잘 작동하는 것을 확인 할 수 있었습니다.



 ▶ multipartFilter를 XSS Filter위에 적용하기 전 requerst를 받아오는 모습과 적용 후 request 비교


먼저 multipartFilter 적용 전 request



다음 web.xml에 multipartFilter를 적용한 후



 request로 넘어오는 값들이 확연히 다른 것을 보실 수 있습니다. multipartParameters를 까보게 되면 해당 페이지에 기입한 여러 값들이 정삭적으로 잘 넘어오는 것을 확인할 수 있었습니다. 이로 인해 제목이나 본문에 스크립트가 들어간다고 해도 XSS Filter를 통해 잘 처리 할 수 있었습니다.

 




반응형
반응형

 JSP/SERVLET 파트에서 SERVLET이 동작하는 흐름에 대해서 알아봤다. 컨테이너에서 서블릿이 초기화되고 그 해당 서블릿이 어떻게 DispatcherServlet에 의해 처리되어 뷰를 반환하게 되는지에 대해 살펴보도록 하겠다.


  DispatcherServlet에 대해 간단히 설명하자면, DispatcherServlet은 Controller로 향하는 모든 웹 요청의 진입점이며 웹 요청을 처리, 결과 데이터를 Client에게 제공하는 역할을 한다.네 맞습니다. DispatcherServlet은 우리가 각각 분리하여 만든 Model 파트와 Controller파트 View 파트를 조합하여 브라우저로 출력해주는 역할을 수행하는 클래스이며 DispatcherServlet으로 인해 web.xml의 역할을 획기적으로 축소시켜 주었다.

예전 DispatcherServlet이 있기전에는 모든 사용자의 요청 url을 일일이 해당 요청을 처리하는 servlet과 매핑시켜주는 작업을 지정해 주었어야만 했다.예를 들어, 기본URL/happy, 기본URL/contents, 기본URL/subject 등의 요청이 들어왔을 때 이에 해당하는 서블릿과의 매핑 작업을 web.xml에 모두 정의해주고 사용했어야 했던 만큼 web.xml 도 복잡해지고 손수 작업에 필요한 서블릿 정의와 매핑작업을 해줘야 했기 때문에 여간 귀찮은 일이 아니였다.

하지만 지금은 web.xml에

이렇게 DispacherServlet을 정의해주고 모든 URL에 대해 매핑을 해주게 되면 DispatcherServlet이 요청 url에 해당하는 컨트롤러를 찾아 매핑해주게 된다. 얼마나 고마운 일인가. 위의 소스코드에 대해 이해가 안가시는 분은  http://blog.naver.com/kim3zz/220273028176 servlet 매핑에 대한 설명 부분을 참고하시길 바란다.


DispatcherServlet은 이렇게 web.xml 을 획기적으로 축소시켜주었고 개발자에게 요청에 따른 컨트롤러를 일일이 매핑해야하는 번거로움 또한 덜어주었다. 이제 그럼 DispatcherServlet이 어떻게 동작하는지에 대해 알아보자.

[ 그림 1 ] 사용자가 특정 URL을 요청하게 되고 웹서와 컨테이너를 거쳐 해당 요청이 DispatcherServlet을 타게 된다.

[ 그림 2 ] DispatcherServlet은 요청에 대한 정보를 HandlerMapping에게 보내 요청을 처리할 수 있는 Controller을 찾아 DispatcherServlet에게 다시 반환하게 됩니다. HandlerMapping은 클라이언트 요청을 어떤 Controller가 수행할지의 여부를 결정해 주며 스프링의 디폴트 전략에 의해 BeanNameUrlHandlerMapping이 설정되어 있어 따로 설정을 하지 않아도 요청 url과 동일한 이름을 갖는 Controller을 찾아 매핑시켜 주게 된다.

[ 그림 3 ] DispatcherServlet은 해당 컨트롤러에게 요청에 대한 처리를 부탁하고 컨트롤러는 요청을 처리한 후에 응답받을 ModelAndView를 리턴하게 됩니다.

[ 그림 4, 5 ] ViewResolver는 컨트롤러가 반환한 ModelAndView를 받아 해당 view가 존재하는지 검색하게 됩니다. 해당 View가 있다면 전처리 과정을 거쳐 해당 View를 반환해 줍니다.

InternalResouceViewResolver를 보시면 name="prefix"와 "suffix"를 보실 수 있는데 컨트롤러가 던지 view 앞에 붙여지는 것이 prefix이고 뒤에 붙여지는것이 jsp가 되게 됩니다. 예를 들어 컨트롤러가 "board"라는 뷰 스트링 객체를 던졌다면 리졸버를 통해 /WEB-INF/views/board.jsp 가 되어 해당 뷰에서 요청이 보여지게 됩니다.

다음에는 web.xml에서는 어떠한 작업들이 이루어지는 지에 대해 살펴보도록 하겠습니다.

ref :https://kisukpark.wordpress.com/2013/08/29/spring-mvc-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90/http://egloos.zum.com/springmvc/v/504151




반응형

+ Recent posts