IT/Spring

Spring & 보안 정리

바바옄 2015. 5. 14. 04:06
반응형

Spring

- 사실상 업계 표준 프레임 워크

Maven

- Spring을 사용하기 위해 Maven Build가 필요

Spring의 의존 라이브러리를 간편하게 추가 할 수 있도록 의존성 주입을 제공

- 그 외 오픈 소스 라이브러리도 Maven Repository에 업로드 함으로써 대부분의 라이브러리를 자동으로 추가 가능

- 프로젝트의 구조를 자동으로 구성

- Build를 통해 배포를 위한 파일을 생성

Spring = DI Framework = IoC Framework

DI / IoC

- JAVA의 Class 상속/Interface를 이용한 추상화를 기반으로 하는 개발 방법

- Spring은 아래 DI / IOC를 강력하게 지원하는 프레임 워크

DI : Dependency Injection (의존성 주입)

- 프로그램에 필요한 각종 클래스들을 Bean Container에 두고 필요할 때마다 불러와서 사용

- 완벽한 싱글톤 객체(빈 스코프에 따라 다름) -> Read만 가능 Write불가-> 복제 불가

IoC : Inversion of Control (제어의 역전)

- 프로그램이 흘러가는 순서를 변경 가능

- DI는 IoC 패턴의 구현체 중 하나

- DI에 따라 프로그램의 흐름이 완전히 변경

- Spring은 DI를 기준으로 많은 framework module이 만들어짐

클래스 : 기능 + 속성


인터페이스  :  추상화된 기능(구현체가 없음.) 가지고 있다.


Spring은 오로지 인터페이스만 가지고 통신을 하겠다. -> 인터페이스에는 기능이 정의만 되어 있고 구현이 안되있음


-> 클래스는 DI 이용해서 스프링에 주입 -> 우리가 Context 등록한대로 프로그램이 흘러간다.


DI 쓰는 이유 : new 키워드(강한결합) 없애자.(어떤 클래스가 사용 되는지 알 수 없도록)


bean container안의 내용들은 싱글톤 객체이기 때문에 복제가 불가능 하다.



Spring AOP (Aspect Oriented Programming) - 관점 지향 프로그래밍


꼭 기억해야 할 것 - Weaving



JUnit


- 단위 테스트 툴

- 기능 하나 하나를 다 테스트 하겠다.

- 품질에 대한 보증이 가능

- 어떤 소스를 refactoring 했을 때, 이 소스를 검증하기 제일 쉬운 방법

- Spring이 JUnit으로 개발 됨.


MVC(Model View Contorller)

- 일종의 개발 패러다임

- Model 1 방식의 개발 벙법을 사용했을 때 발생되는 단점들을 보완하기 위한 개발 방법으로 Model2 방식 혹은 MVC 

방식이라고 불림

Model, View, Contorller로 나뉘어 짐

- Controller는 URL 요청에 알맞은 Java Class 의 Method를 실행

- View는 JSP 자체를 뜻하며, Model 2 방식에서는 Scriptlet를 사용하지 않는다.

- Model은 View로 전달되는 객체들을 의미함

- Model1 방식의 최대 단점인 유지보수의 어려움을 쉽게 해결할 수 있다.

- 비즈니스 로직 / 데이터 로직 / View가 각각 분리되어 있어 Pair Programming이 가능해진다.

- 객체지향의 특성을 깨는 단점이 있다. 


Spring MVC를 쓰기 위해 꼭 필요한 것

1. dispatcher servlet

2. web.xml

3. pom.xml


Encoding Filter


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    <!-- 
        영어권을 제외한 모든 나라에 서비스할 경우,
        그리고 글로벌 서비스를 할 경우 (다국어지원)
        모든 문자를 UTF-8로 변경할 필요가 있다.
        
        모든 페이지에서 
        HttpServletReqeust.setCharacterEncoding("UTF-8");
        을 사용하기에는 많은 공수가 필요하고 수정의 불편함이 존재한다.
        
        이런 문제는 Spring에서 지원해주는 EncodingFilter를 사용해서
        해결한다.
        
        Filter 는 DispatcherServlet이 요청을 전달받기 전에
        실행되는데, Filter에서 모든 요청을 받아 
        Encoding을 UTF-8로 변경한 다음 DispatcherServlet으로 전달한다.
    -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    
    <!-- 
        characterEncodingFilter가 모든 요청에 대해서
        Encoding을 변경해주기 위해서는 url-pattern을
        /* 로 변경을 해주어야 한다.
    -->
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
cs



annotation-driven

1
2
3
4
5
6
7
8
<!--
        Controller 탐색을 위한 HandlerMapping과 HandlerAdapter를
        자동으로 설정해준다.
        mvc:annotation-driven을 사용하지 않을 경우
        HandlerMapping과 HanlderAdapter는 수동으로 설정해야 한다.
    -->
    <mvc:annotation-driven />
 
cs


ViewResolver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!--
        Controller에서 ModelAndView 를 이용한 View를 찾을 때 사용된다.
        ModelAndView.setViewName(ViewName); 으로 View를 찾는다.
        
        이 때, View 는 viewResolver에 등록된 경로로 찾아가는데
        prefix + ViewName + suffix 의 조합으로 찾는다.
        예를 들어, ModelAndView.setViewName("board/list"); 로 
        정했다면 실제 View의 위치는
        /WEB-INF/view/board/list.jsp 가 된다.
        /WEB-INF/view/ 는 prefix에 설정된 내용이고
        .jsp 는 suffix에 설정된 내용이다.
        
        * Controller 에서 String을 Return 할 경우에도
          viewName을 찾는다.
    -->
    <bean    id="viewResolver"
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>
 
cs


Static File(css, js, img) 설정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    <!--
        정적자원 설정하는 부분.
        MVC 를 사용하게 되면 정적 자원에 대한 접근이 불가능해진다.
        그 이유는 모든 요청을 DispatcherServlet 이 받아서 처리하기 때문인데,
        DispatcherServlet으로 요청을 할 경우 정적자원에 대한 접근을 할 수 없다.
        때문에 정적자원에 대한 접근 설정을 따로 해주어야 하는데,
        이 부분이 mvc:resources 부분이다.
        
        mvc:resources 는 location 과 mapping 속성을 가진다.
        location은 정적자원이 존재하는 위치를 뜻하고
        mapping을 정적자원에 접근하기 위한 URL을 의미한다.
        
        아래 설정은 
        http://localhost:8080/ContextPath/resources/js/jquery.js
        로 요청할 경우
        /WEB-INF/resources/js/jquery.js 를 찾게 하는 설정이다.
        
        resources 는 중복하여 설정할 수 도 있는데
        아래처럼 URL을 각각 다르게 해서 접근하도록 할 수 도 있다.
        <mvc:resources    location="/WEB-INF/resources/js/" 
                        mapping="/js/**" />
        <mvc:resources    location="/WEB-INF/resources/css/" 
                        mapping="/css/**" />
        <mvc:resources    location="/WEB-INF/resources/img/" 
                        mapping="/img/**" />
    -->
    <mvc:resources    location="/WEB-INF/resources/" 
                    mapping="/resources/**" />
 
cs


Controller

1
2
3
4
5
6
7
8
9
@Controller
public class TestController{
    
    @RequestMapping("/test")
    public String test(){
        return "test/test";
    }
}
 
cs

String type은 view의 이름을 리턴한다.


view.setViewName("test/test");

// request.setAttribute~~ 와 같은 기능

view.addObject("helloMessage", "Hello");

// key : helloMessage , value : Hello

// view.setViewName()의 ()안의 redirect가 붙으면 view.addObject는 사용할 수 없다.


${helloMessage}

- EL(표현언어)

- 보통 c:out을 붙여서 사용, c:out이 없으면 script를 그대로 실행시켜 코드가 노출 될 가능성이 있다.


전송방식 지정하기

1
2
3
4
5
6
7
8
9
10
11
12
    @RequestMapping(value="/test", method = RequestMethod.GET)
    public ModelAndView test(){
        ModelAndView view = new ModelAndView();
        return view;
    }
    
    @RequestMapping(value="/test1", method = RequestMethod.POST)
    public ModelAndView test1(){
        ModelAndView view = new ModelAndView();
        return view;
    }
 
cs

- form은 항상 post 방식으로 보내야 함. 
- form을 get방식으로 보내면 403 error 발생
- 엔카태그 혹은 나머지 전송방식은 get, post방식 둘 다 가능

파라미터 전송 방식

1. (@PathVariable String id)
2. (HttpServletRequest request)
3. (@RequestParam("id") String id)
4. (MemberVO memberVO)

redirect 처리

컨트롤러에서 클라이언트의 요청을 처리한 후에 다른 페이지로 리다이렉트 하고 싶을 때 아래와 같이 뷰 이름 앞에 redirect: 를 붙이면 된다.
- return "redirect:/test"

/ 시작하면 : 절대 경로로 리다이렉트
/ 시작하지 않으면 : 상대 경로로 리다이렉트


Session

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    @RequestMapping("/test")
    public ModelAndView test(HttpServletRequest request){
        ModelAndView view = new ModelAndView();
        //세션을 받는 첫 번째 방법
        HttpSession session = request.getSession();
        
        return view;
        
    }
    
    @RequestMapping("/test2")
    public ModelAndView test2(HttpSession session){
        ModelAndView view = new ModelAndView();
        //세션을 받는 두 번째 방법
        session.setAttribute("key""value");
        
        return view;
        
    }
 
cs

예외처리

1
2
3
4
5
6
7
8
9
@ControllerAdvice("com.ktds")
public class CommonExeceptionHandler{
    
    @ExceptionHandler(RuntimeException.class)
    public String handleRuntimeException() {
        return "error/commonException";
    }
}
 
cs


com.ktds 의 패키지 아래 RuntimeException 에러가 발생하면

handleRuntimeException() 메소드를 실행하라.



@Controller의 리턴타입

1
2
3
4
5
6
7
8
9
10
            @RequestMapping("/getJson")
            @ResponseBody
            public MemberInfoVO getJson() {
                MemberInfoVO memberInfo = new MemberInfoVO();
                memberInfo.setResult(true);
                memberInfo.setName("장민창");
                memberInfo.setPhoneNumber("010-2737-2604");
                return memberInfo;
            }
 
cs

Ajax 통신을 가장 많이 쓰이는 Return Type JSON Type 이다.


기존의 방법대로라면 JSON Type 일일이 String 으로 작성해서 리턴시켜야 하는데,  


@ResponseBody 라는 Annotation 이용해서 VO(Value Object) 리턴시키면


자동으로 JSON Type으로 변경 시켜준다.


또한, JSP 에서 데이터를 받을 JSON Parse 필요도 없다.




Interceptor


-    모든 페이지마다 접근 제어를 다르게 해야 한다거나(인증/인가),

사용자가 특정 URL을 요청할 때 마다 접근내역을 기록하고 싶을 때(모니터링),

혹은 로그인 체크를 해야할 때 Interceptor를 사용한다.


인터셉터는 총 3 부분에 대해 공통 기능을 넣을 수 있다.


1. 컨트롤러 실행 전

2. 컨트롤러 실행 후, 아직 뷰를 실행하기 전

3. 뷰를 실행 한 후



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    //1.
    <mvc:interceptors>
        <bean id="measeuringInterceptor" class="com.ktds.intercept.MeasuringInterceptor"></bean>
    </mvc:interceptors>
    
    //2.
    <mvc:interceptors>
            <bean id="measeuringInterceptor" class="com.ktds.intercept.MeasuringInterceptor"></bean>
        <mvc:interceptor>
            <mvc:mapping path="/detail/**/"/>
            <mvc:mapping path="/list"/>
            <mvc:exclude-mapping path="/write"/>
            <mvc:exclude-mapping path="/dowrite"/>
        </mvc:interceptor>
    </mvc:interceptors>
 
cs



//1. 모든 url에서 다 처리

//2. 아래 부분에 해당하는 곳만 처리
<mvc:interceptor>
            <mvc:mapping path="/detail/**/"/>
            <mvc:mapping path="/list"/>
            <mvc:exclude-mapping path="/write"/>
            <mvc:exclude-mapping path="/dowrite"/>
</mvc:interceptor>


Logback Log Level

Trace 는 Trace, Debug, Info, Warn, Error를 포함

- logger.trace("");

Debug Debug, Info, Warn, Error를 포함

- logger.debug("");

Info Info, Warn, Error를 포함

- logger.info("");

Warn Warn, Error를 포함

- logger.warn("");

Error는 Error만 포함

- logger.error("");


bean config 설정 분리하기

- bean의 설정이 DispatcherServlet에 모두 설정이 되면 파일이 너무 커져 불편함이 있다.

- controller 이하는 각 context로 분리 시킨다.


보안


sql injection 공격이 가능한 상황 


- preparestatement를 사용하지 않았을 때(statement사용했을 때)


- ? 사용하지 않았을 때


command injection


- 서버에 직접 접속해서 공격


- whiteList 사용하면 간단하게 막을 있다.


xss 


공격방법


1. reflective xss


2. stored xss

3. dom xss


Lucy-XSS-FILTER 사용해서 막을 수 있다. (jsp)


CSRF


Xss 막는 방법으로 있으나, 완전히 막지는 못해


로그인 토큰 발급을 통해 완전히 막을 있다


로그인 시도 횟수 제한


보안 주관식(어려움)

1. injection 공격

2. capsulation


3. 암호화


4. exception



RuntimeException Exception 차이점


1. 예외란? (Error vs Exception)

먼저 오류(Error)와 예외(Exception)의 개념을 정리하고 넘어가자.

오류(Error)는 시스템에 비정상적인 상황이 생겼을 때 발생한다. 이는 시스템 레벨에서 발생하기 때문에 심각한 수준의 오류이다. 따라서 개발자가 미리 예측하여 처리할 수 없기 때문에, 애플리케이션에서 오류에 대한 처리를 신경 쓰지 않아도 된다.

오류가 시스템 레벨에서 발생한다면, 예외(Exception)는 개발자가 구현한 로직에서 발생한다. 즉, 예외는 발생할 상황을 미리 예측하여 처리할 수 있다. 즉, 예외는 개발자가 처리할 수 있기 때문에 예외를 구분하고 그에 따른 처리 방법을 명확히 알고 적용하는 것이 중요하다.

모든 예외클래스는 Throwable 클래스를 상속받고 있으며, Throwable은 최상위 클래스 Object의 자식 클래스이다.

Trowable을 상속받는 클래스는 Error와 Exception이 있다. Error는 시스템 레벨의 심각한 수준의 에러이기 때문에 시스템에 변화를 주어 문제를 처리해야 하는 경우가 일반적이다. 반면에 Exception은 개발자가 로직을 추가하여 처리할 수 있다.

Exception은 수많은 자식클래스를 가지고 있다. 그 중 RuntimeException을 주목해야 한다. RuntimeException은 CheckedException과 UncheckedException을 구분하는 기준이다. Exception의 자식 클래스 중 RuntimeException을 제외한 모든 클래스는 CheckedException이며, RuntimeException과 그의 자식 클래스들을 Unchecked Exception이라 부른다. CheckedException과 UncheckedException에 대해 더 자세히 살펴보자.

Checked Exception과 Unchecked Exception의 가장 명확한 구분 기준은 ‘꼭 처리를 해야 하느냐’이다. Checked Exception이 발생할 가능성이 있는 메소드라면 반드시 로직을 try/catch로 감싸거나 throw로 던져서 처리해야 한다. 반면에 Unchecked Exception은 명시적인 예외처리를 하지 않아도 된다. 이 예외는 피할 수 있지만 개발자가 부주의해서 발생하는 경우가 대부분이고, 미리 예측하지 못했던 상황에서 발생하는 예외가 아니기 때문에 굳이 로직으로 처리를 할 필요가 없도록 만들어져 있다.

또한 예외를 확인할 수 있는 시점에서도 구분할 수 있다. 일반적으로 컴파일 단계에서 명확하게 Exception 체크가 가능한 것을 Checked Exception이라 하며, 실행과정 중 어떠한 특정 논리에 의해 발견되는 Exception을 Unchecked Exception이라 한다. 따라서 컴파일 단계에서 확인할 수 없는 예외라 하여 Unchecked Exception이며, 실행과정 중 발견된다 하여서 Runtime Exception이라 하는 것이다.

그리고 한 가지 더 인지하고 있으면 좋은 것이 있다. 바로 예외발생시 트랜잭션의 roll-back 여부이다. 기본적으로 Checked Exception은 예외가 발생하면 트랜잭션을 roll-back하지 않고 예외를 던져준다. 하지만 Unchecked Exception은 예외 발생 시 트랜잭션을 roll-back한다는 점에서 차이가 있다. 트랜잭션의 전파방식 즉, 어떻게 묶어놓느냐에 따라서 Checked Exception이냐 Unchecked Exception이냐의 영향도가 크다. roll-back이 되는 범위가 달라지기 때문에 개발자가 이를 인지하지 못하면, 실행결과가 맞지 않거나 예상치 못한 예외가 발생할 수 있다. 그러므로 이를 인지하고 트랜잭션을 적용시킬 때 전파방식(propagation behavior)과 롤백규칙 등을 적절히 사용하면 더욱 효율적인 애플리케이션을 구현할 수 있을 것이다.



반응형

'IT > Spring' 카테고리의 다른 글

Spring 파일 업로드를 위한 multipartResolver bean 추가  (0) 2015.05.19
Maven 프로젝트 설정  (0) 2015.05.08
스프링에서 Sitemesh 설정  (0) 2015.04.30
Layer  (0) 2015.04.30
파일내용을 게시판에 Write  (0) 2015.04.28