예외처리 / PLSQL

조수경·2022년 2월 11일
0

Spring

목록 보기
23/43
  1. 예외처리란?
  • 프로그램을 처리되는 동안 문제가 발생 시 처리를 중단하고 다른 처리를 하는 것
  • 웹 컨테이너(tomcat)는 기본 오류 페이지를 표시해줌
  • 화면에 서버의 내부 정보가 일반인에게 노출되어 보안이 취약해지고 공격을 받을 수 있으므로 최대한 개발자가 직접 예외를 처리하여 정의한 오류 페이지를 표시하게 해줘야 함
  1. 예외 종류
  • 시스템 예외
  • 의존 라이브러리에서 발생한 예외
  • 사용자 정의 예외
  • 스프링 프레임워크 예외
  1. 예외 발생 예시
  • 등록 시 필수여야 하는데 빈 값을 입력하는 유효값 검증 예외
  • 수정 화면 생성 시 뷰 파일에서의 예외
  • 삭제 시 매핑 파일에서의 예외
  • 없는 글에 접근 시 예외
  • 없는 URL 요청 시 예외

web.xml 설정

<error-page>
	<error-code>400</error-code>
	<location>/WEB-INF/views/error/400.jsp</location>
</error-page>
<error-page>
	<error-code>404</error-code>
	<location>/WEB-INF/views/error/404.jsp</location>
</error-page>
<error-page>
	<error-code>500</error-code>
	<location>/WEB-INF/views/error/500.jsp</location>
</error-page>

컨트롤러

      /error400 , 500.. 404 요청시(오류 발생시) tile-config.xml에
      <definition name="*/*" extends="tiles-layout">
              <put-attribute name="body" value="/WEB-INF/views/{1}/{2}.jsp" />
          </definition>

로 흡수되어 컨트롤러의 해당하는 메서드 실행됨

package kr.or.ddit;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ErrorController {
    @RequestMapping(value="/error/400")
    public String error400() {
        return "error/400";
    }
    @RequestMapping(value="/error/404")
    public String error404() {
        return "error/404";
    }
    @RequestMapping(value="/error/500")
    public String error500() {
        return "error/500";
    }
}

<사전 지식>

--PL/SQL(절차적 언어로써의 질의어)

--User Defined Function(사용자 정의 함수)

/*

  1. CREATE OR REPLACE FUNCTION 사용자정의함수명(바인드변수...)

  2. 반환값이 있음. 일반 오라클 내장함수

    ( ex) LENGTH, SUBSTR, INSTR, TO_CHAR...)처럼 사용할 수 있음

  3. 반환할 데이터 타입을 RETURN으로 선언해야 함

  4. 실행영역에서도 RETURN문이 있어야 함

*/

/

SET SERVEROUTPUT ON;

/

--P_EMP_NUM : 바인드 변수(IN/OUT) => 파라미터를 받거나 보내거나..

CREATE OR REPLACE FUNCTION FN_MEMNAME(P_EMP_NUM IN VARCHAR2)

RETURN VARCHAR2

IS

--SCALAR변수

R_NM VARCHAR2(100);

BEGIN

--PL/SQL에서의 SELECT에는 꼭 INTO문이 있어야 함

SELECT NM INTO R_NM

FROM   EMP

WHERE  EMP_NUM = P_EMP_NUM;



DBMS_OUTPUT.PUT_LINE('생성 완료!');



RETURN R_NM;

END;

/

--자동차번호를 통해 고객의 명을 알고자 할때..

--33너1122

--EQUI JOIN

SELECT *

FROM CAR A, CUS B

WHERE A.CUS_NUM = B.CUS_NUM

AND A.CAR_NUM = '33너1122';

--INNER JOIN(ANSI표준)

SELECT B.CUS_NM

FROM CAR A INNER JOIN CUS B ON(A.CUS_NUM = B.CUS_NUM)

WHERE A.CAR_NUM = '33너1122';

/

CREATE OR REPLACE FUNCTION FN_GET_CUS_NM(P_CAR_NUM IN VARCHAR2)

RETURN VARCHAR2

IS

--REFERENCE변수

--VARCHAR2(100)

R_CUS_NM CUS.CUS_NM%TYPE;

BEGIN

SELECT B.CUS_NM INTO R_CUS_NM

FROM   CAR A INNER JOIN CUS B ON(A.CUS_NUM = B.CUS_NUM)

WHERE  A.CAR_NUM = P_CAR_NUM;



RETURN R_CUS_NM;

END;

/

SELECT CAR_NUM, MK, PY, DRI_DIST, FN_GET_CUS_NM(CAR_NUM) CUS_NM FROM CAR;

/

/*

Package

  1. 꾸러미, 포장한 상품이라는 의미

  2. 업무상 관련 있는 것을 하나로 묶어서 사용

  3. 여러 변수, Cursor, Function, Procedure, Exception을 묶어서 캡슐화함

  4. 선언부와 본문 이렇게 두 부분으로 나뉨

  5. 선언부는 패키지에 포함될 변수, Procedure, function 등을 선언함

*/

/

--선언부

CREATE OR REPLACE PACKAGE PKG_GET_NM

IS

FUNCTION FN_MEMNAME(P_EMP_NUM IN VARCHAR2) RETURN VARCHAR2;

FUNCTION FN_GET_CUS_NM(P_CAR_NUM IN VARCHAR2) RETURN VARCHAR2;

END;

/

--본문

CREATE OR REPLACE PACKAGE BODY PKG_GET_NM

IS

--첫번째 함수 BODY

FUNCTION FN_MEMNAME(P_EMP_NUM IN VARCHAR2) RETURN VARCHAR2

IS

--SCALAR변수

    R_NM VARCHAR2(100);

BEGIN

    --PL/SQL에서의 SELECT에는 꼭 INTO문이 있어야 함

    SELECT NM INTO R_NM

    FROM   EMP

    WHERE  EMP_NUM = P_EMP_NUM;

   

    DBMS_OUTPUT.PUT_LINE('생성 완료!');

   

    RETURN R_NM;

END FN_MEMNAME;

--두번째 함수BODY

FUNCTION FN_GET_CUS_NM(P_CAR_NUM IN VARCHAR2) RETURN VARCHAR2

IS

    R_CUS_NM CUS.CUS_NM%TYPE;

BEGIN

    SELECT B.CUS_NM INTO R_CUS_NM

    FROM   CAR A INNER JOIN CUS B ON(A.CUS_NUM = B.CUS_NUM)

    WHERE  A.CAR_NUM = P_CAR_NUM;

   

    RETURN R_CUS_NM;

END FN_GET_CUS_NM;

END PKG_GET_NM;

/

SELECT CAR_NUM, MK, PY, DRI_DIST, PKG_GET_NM.FN_GET_CUS_NM(CAR_NUM) CUS_NM FROM CAR;

<실습>

/*

PLS-00201: identifier 'DBMS_CRYPTO' must be declared

는 권한 문제이네요..

sys의 DBMS_CRYPTO 패키지의 실행권한을 유저에게 주시면 됩니다.

GRANT EXECUTE ON DBMS_CRYPTO TO 사용자;

GRANT EXECUTE ON DBMS_CRYPTO TO PUBLIC;

GRANT EXECUTE ON DBMS_OBFUSCATION_TOOLKIT TO PUBLIC;

*/

/

SET SERVEROUTPUT ON;

/

CREATE OR REPLACE PACKAGE pkg_crypto

IS

FUNCTION encrypt ( input_string IN VARCHAR2 ) RETURN RAW;

FUNCTION decrypt ( input_string IN VARCHAR2 ) RETURN VARCHAR2;

END pkg_crypto;

/

CREATE OR REPLACE PACKAGE BODY pkg_crypto

IS

-- 에러 발생시에 error code 와 message를 받기 위한 변수 지정.

SQLERRMSG   VARCHAR2(255);

SQLERRCDE   NUMBER;



FUNCTION encrypt (input_string IN VARCHAR2 )

 RETURN RAW

IS

    key_data_raw        RAW(64);

    converted_raw       RAW(64);

    encrypted_raw       RAW(64);

BEGIN

    -- 들어온 data 와 암호 키를 각각 RAW 로 변환한다.

    converted_raw := UTL_I18N.STRING_TO_RAW(input_string , 'AL32UTF8');

    key_data_raw  := UTL_I18N.STRING_TO_RAW(  '12345678' , 'AL32UTF8');



    -- DBMS_CRYPTO.ENCRYPT 로 암호화 하여 encrypted_raw 에 저장.

    encrypted_raw := DBMS_CRYPTO.ENCRYPT(  src => converted_raw ,

               typ => DBMS_CRYPTO.DES_CBC_PKCS5 , -- typ 부분만 변경하면 원하는 알고리즘을 사용할 수 있다. key value byte 가 다 다르니 확인해야 한다.

               key => key_data_raw ,

               iv =>  NULL);

    RETURN encrypted_raw;

END encrypt;



FUNCTION decrypt (input_string IN VARCHAR2 )

 RETURN VARCHAR2

IS

    converted_string    VARCHAR2(64);

    key_data_raw        RAW(64);

    decrypted_raw       VARCHAR2(64);

BEGIN

    key_data_raw := UTL_I18N.STRING_TO_RAW(  '12345678' , 'AL32UTF8');

    decrypted_raw := DBMS_CRYPTO.DECRYPT( src => input_string ,

                                          typ => DBMS_CRYPTO.DES_CBC_PKCS5 ,

                                          key => key_data_raw ,

                                          iv =>  NULL);



    -- DBMS_CRYPTO.DECRYPT 수행 결과 나온 복호화 된 raw data를 varchar2로 변환하면 끝!

    converted_string := UTL_I18N.RAW_TO_CHAR(decrypted_raw, 'AL32UTF8');

    RETURN converted_string;

END decrypt ;

END pkg_crypto;

/

--grant execute on ddit.pkg_crypto to 계정;

/

--패키지가 정상적으로 생성되었는지 테스트

SELECT PKG_CRYPTO.ENCRYPT('test') from dual;

SELECT PKG_CRYPTO.DECRYPT(PKG_CRYPTO.ENCRYPT('test')) FROM DUAL;

--테스트 테이블 생성

CREATE TABLE TEST_CRYPTO (ID INT , PWD VARCHAR2(64)) ;

INSERT INTO TEST_CRYPTO VALUES (1, PKG_CRYPTO.ENCRYPT('a1234b'));

INSERT INTO TEST_CRYPTO VALUES (2, PKG_CRYPTO.ENCRYPT('c1234d'));

COMMIT;


SELECT ID

 , PKG_CRYPTO.DECRYPT(PWD)

FROM TEST_CRYPTO;

profile
신입 개발자 입니다!!!

0개의 댓글