XpressEngine

[기초] XE구조의 비밀 그 일곱번째 - 사용자의 위험한 발언 (ruleset, filter)

프로그램과 사용자의 소통 도구인 폼(form)!!

XE도 폼전송을 통해 사용자와 소통하고 있습니다. 

아래처럼 처리를 위한 act로 폼값을 보내면 처리되겠지요.


<form action="/" method="post>

<input type="hidden" name="module" value="모듈이름" />

<input type="hidden" name="act" value="처리를 위한 act" />

.....

</form>


하지만, 위 폼은 사용자가 입력한 데이터를 바로 서버로 보내버립니다.

즉, 사용자가 올바르지않은 데이터를 서버에 보내면 처리능력무력화,비정상적인 접근가능,데이터조작 등의 위험이 발생할 수 있습니다.

예를 들면 숫자입력폼에 문자를 입력했다든지,필수입력 폼에 입력을 하지않았다든지...등을 할 수 있습니다.


그래서 친절한 XE에서는 폼전송시 이 폼에 올바른 데이터가 입력되어있는 지 검증하는 도구를 제공하고 있습니다.

만약 XE에 유효성 검사도구가 없었다면 개발자가 직접 구현해야겠지요.. 친절한 XE~

바로 ruleset과 filter라는 유효성 검증 도구입니다.


1. filter

filter적용시 폼전송전 자바스크립트를 이용해 폼 데이터를 검사합니다.

그리고 아무이상없으면 서버에 전송하고, 결과값을 얻어 지정한 자바스크립트 콜백함수를 실행시킵니다.

참고로 폼값 서버전송할때 AJAX기술이용해 전송하므로 새로고침없이 폼값이 전송됩니다.


filter 적용법


① filter XML를 작성합니다. (작성된 filter XML은 보통 /modules/모듈명/tpl/filter 에 저장합니다.)

<filter name="filter 이름" module="모듈이름" act="처리할 act메서드" confirm_msg_code="confirm 메시지 (언어코드로 작성)">

    <form>

        <node target="폼이름" required="true" maxlength="40" filter="number" />

    </form>

    <parameter>

        <param name="폼이름" target="서버에 전송될 폼이름" />

    </parameter>

    <response callback_func="콜백함수 이름">

        <tag name="error" />

        <tag name="message" />

        <tag name="콜백함수실행시 넘겨줄 변수" />

    </response>

</filter>


filter 이름은 알기쉬운 영문이름으로 정하세요.

- 보통 "filter 이름.xml"이란 이름으로 파일저장합니다.

- 주황색 으로 표시되어있는 부분은 있어도 되고 없어도 되는 부분입니다.

- confirm 메시지를 지정하면 폼전송전 confirm 메시지가 뛰워집니다. (~~ 하시겠습니까? )

- <form>에는 폼에 대한 규칙을 정할 수 있습니다. (required="true" : 필수입력 , maxlength="40" : 최대 40자 입력 제한 , filter="number" : 숫자만입력 등...)

<parameter>항목을 지정하면 지정한 폼값들만 서버로 전송합니다. 한개도 지정하지않으면 모든 폼값이 전송됩니다.

- <tag name="콜백함수실행시 넘겨줄 변수" /> 항목을 넣으면 폼값전송후 콜백함수 실행시 서버로부터 받은 변수를 사용할 수 있습니다. 이때 서버에서는 $this->add('변수명', '값') 를 사용하여 변수를 추가해야합니다.


② 폼값전송후 실행할 자바스크립트 콜백함수를 만듭니다. (콜백함수는 filter XML에서 지정합니다.)

function [filter XML에서 지정한 콜백함수이름](ret_obj) {

    var error = ret_obj['error'];

    var message = ret_obj['message'];

    alert(message);

}

이 함수는 서버결과 message를 받아 alert메시지를 뛰웁니다.

인자로 받은 ret_obj에는 서버에서 받아온 결과값이 저장 되어 있습니다. (ret_obj['message'] 처럼 사용)


③ filter 적용할 페이지 (act 메서드)에 filter XML를 불려오는 코드를 추가합니다.

Context::addJsFilter($this->module_path.'tpl/filter', filter XML파일이름);

* <!--%import("filter XML파일(경로포함)")-->를 사용해 html 템플릿 파일에서도 불려오는 코드를 작성할 수 있습니다.


④ 폼전송시 procFilter라는 자바스크립트함수가 실행되어지도록 코드를 삽입합니다. 

<form action="/" method="post" onsubmit="return procFilter(this, 필터이름)" >



2. ruleset

filter기능은 클라이언트에서만 폼값을 검사하고, 직접적으로 처리할 서버에서는 검사하지않고, 바로 처리해버립니다.

하지만 ruleset기능은 클라이언트에서 자바스크립트를 이용해 폼값을 검사하고, 한번더 서버에도 유효성 검사를 합니다.

왜냐면 클라이언트에서 조작해 바로 서버로 보낼 수 있는 가능성이 있어 한번더 서버에서도 검사를 진행하여 올바르지않은 데이터를 막기위함입니다.


ruleset기능은 filter와 다르게 AJAX기술이용해 전송하지않고 기본적인 폼(form)을 통해 전송됩니다.

그래서 ruleset기능 적용시 새로고침 없이 하려면 따로 AJAX기술을 가지고 구현해주어야합니다.


그리고 filter기능은 XE 태초부터 있었던 기능이지만, ruleset기능은 XE Core 1.5부터 추가되었습니다.

즉, ruleset기능 사용시 XE Core 1.5 하위버전에서 호환문제가 발생할 수 있습니다.


ruleset 적용법


① ruleset XML를 작성합니다. (ruleset XML은 XE가 읽을 수 있도록 /modules/모듈명/ruleset에 저장해야합니다.)

<?xml version="1.0" encoding="utf-8"?>

<ruleset version="1.5.0">

<customrules>

<rule name="규칙이름" type="규칙종류" test="규칙종류에 따른 코드" />

</customrules>

<fields>

<field name="폼이름" required="true" length="최소:최대" rule="규칙이름" default="기본값" equalto="일치해야될 폼" modifier="rule적용수정 문자열" />

</fields>

</ruleset>


- 파일이름을 "룰셋이름.xml"로 저장해야합니다.

- <ruleset version="1.5.0">은 XE에 롤셋파일을 읽을때 이 버전에 따라 다르게 읽습니다.

주황색 으로 표시되어있는 부분은 있어도 되고 없어도 되는 부분입니다.

- <fields>에는 폼에 대한 규칙을 정할 수 있습니다. 속성은 다음과 같습니다.

  • name="폼이름" : 폼이름
  • required="true" : 필수입력
  • length="최소:최대" : 최소자 ~ 최대자로 입력 제한
  • rule="규칙이름" : 규칙적용
  • default="기본값" : 기본값
  • equalto="일치해야될 폼이름" : 패스워드 다시입력 같이 다른폼과 같이 일치해야됨
  • modifier="rule적용수정 문자열" : modifier="not"일경우 규칙적용 결과를 반대로 바꿉니다. 예를 들어 rule="number" modifier="not" 경우 정수숫자가 아니면 규칙통과가 됩니다.


- 다음과 같은 이미 만들어진 rule(규칙)을 적용할 수 있습니다. (rule="number"와 같이)

  • email : 메일 주소
  • userid : 사용자 아이디
  • url : URL
  • alpha : 영문자
  • alpha_number : 영문자 및 숫자, 언더스코어
  • number : 정수 숫자


<customrules>에는 사용자가 rule="number"와 같은 rule(규칙)을 직접만들 수 있습니다.

- 사용자가 만든 rule(규칙)의 (통과하지않을 때의) 메시지 지정할 수 있습니다.

(예시)

<rule name="imageExtension" type="regex" test="/\.(gif|jpg|jpeg|gif|png|swf|flv)$/i">

<message xml:lang="ko">%s은 gif, png, jpg, swf, flv 파일만 가능합니다.</message>

</rule>


- 폼이름이 {$lang->폼이름} 언어파일에 저장되어있지않은 경우 "pint_er는 숫자로만 입력가능합니다." 이런식으로 규칙통과하지않을 때의 메시지가 나오게 됩니다. 이럴때 pint_er라는 이름으로 언어파일에 저장하면 되지만, 상황에 따라 안될 경우 ruleset에서 한글이름을 정해주면 됩니다.

(예시)

<field name="user_layout_image" required="true" rule="imageExtension">

<title xml:lang="ko">파일</title>

</field>


- if문을 사용해 변수에 따라 rule적용을 다르게 할 수 있습니다. 변수는 "$폼이름" 형식으로 써야합니다.

(예시)

<field name="password">

<if test="!$member_srl" attr="required" value="true" />

<if test="!$member_srl" attr="length" value="3:20" />

</field>


rule은 ,(콤마)로 구분하여서 여러개 사용할 수 있습니다. 이때 ,(콤마)의 의미는 and입니다. (rule="number,userid")

- 규칙종류에는 regex, enum, expression 가 있습니다. 사용법은 아래와 같습니다.

  • regex : 정규식으로 rule 만듬.. 예시 - <rule name="signed_number" type="regex" test="/-?[0-9]+/" />
  • enum : 정해진 문자들로만 입력할 수 있는 rule 만듬.. 예시 - <rule name="boolean" type="enum" test="Y,N" />
  • expr : 수식으로 rule 만듬.. 예시 - <rule name="less_than_1000" type="expr" test="$$ &lt; 1000" />
* $$ 는 폼값을 의미합니다.


② action에 ruleset 속성을 삽입합니다. (그러면 해당 act에 데이터가 들어올 경우 서버에서 ruleset을 통해 유효성 검증을 시도합니다.)

/modules/모듈명/conf/module.xml(act정의파일)에서 

<action name="act이름" type="controller" ruleset="룰셋이름" standalone="false" />

위와 같이 ruleset 속성을 삽입하면 됩니다.


예시 - <action name="procBoardInsertDocument" type="controller" ruleset="insertDocument" standalone="false" />


③ HTML템플릿파일에서 폼에 ruleset 속성을 삽입합니다. (그러면 템플릿 컴파일시 ruleset을 사용할 수 있도록 자동셋팅됩니다.)

<form ruleset="룰셋이름" action="/" method="post">



* 룰셋이름 앞에 "@"를 붙일 경우 ruleset파일을 /modules/모듈명/ruleset 에서가 아닌 /files/ruleset에서 불려옵니다.

예시 - ruleset="@login"


어떤경우에 사용할까요?

ruleset 파일이 동적으로 변할 경우 사용합니다.

예를 들어 회원아이디는 "일반ID"와 "이메일 주소" 중 하나를 선택해서 사용할 수 있습니다.

회원아이디를 무엇을 사용하냐는 오로지 사용자 설정에 달려있게 됩니다.


일반ID를 사용할 경우

<field name="user_id" required="true" rule="userid" />


이메일 주소를 사용할 경우

<field name="user_id" required="true" rule="email" />


이렇게 사용자 설정에 따라 rule을 각각 다르게 적용해야합니다.

그래서 member 모듈에서는 사용자 설정에 따라 동적으로 룰셋파일을 새로 작성합니다. 그리고 /files/ruleset 에 저장하는 거지요.

그러면 @login사용시 /files/ruleset/login.xml 파일이 불려오게 됩니다.


  • ?
    날아라 2014.03.12 01:12:40
    필터는 추후 코어에서 계속 지원하는건가요? 1.5부터는 룰셋으로 사용한다고 했던것 같은데.
  • profile
    CONORY 2014.03.12 09:11:02

    글세요.. 프로그램 호완문제 때문이라도 계속지원되지않을까요?
    많은 프로그램들 필터기능을 사용하고 있는 데 필터기능이 없어지면 옛날 프로그램은 사용못하겠죠..
    참고로 지금도 게시판 모듈에서는 글쓸때 필터기능을 사용합니다.. 그리고 서버에서 롤셋기능을 사용하도록 되어있네요..
    한마디로 필터기능 (AJAX전송)과 롤셋기능(서버에서 유효성 검사)을 같이 사용한 거죠.. 어라? 그러고보니, 장점과 장점이 결합했네요..ㅎㅎ

  • ?
    다이오니 2015.02.02 01:20:20
    정말 XE는 xml파일들이 중요한 역할을 하는 것 같아요~
?