웹마스터 팁

Draggable Captcha System for XE1.7.5 Member Module

QapTcha for XpressEngine 1.7.5


스팸 회원가입을 차단하기 위한 드래그 버튼 방식의 캡챠를 XE 회원가입 폼에 적용하는 내용입니다.

코어 1.7.5 에서 테스트하였으며, 수정된 Member Module의 기본스킨(default) 파일을 첨부합니다. 

이전 버전, 또는 기본스킨 이외의 스킨사용으로 발생하는 오류 등에 대해서는 질문을 받지 않습니다.

오픈소스 플러그인을 포함하고 있으므로 비영리적 재배포만 무한자유로 가능합니다. 

Happy World Wide Web!


QapTcha-DEMO.jpg




1. QapTcha 언어 설정


./modules/member/lang/lang.xml
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
<!--// Qaptcha Language items -->
    <item name="draggable_qaptcha">
        <value xml:lang="ko"><![CDATA[캡챠 드래그 버튼]]></value>
        <value xml:lang="en"><![CDATA[Draggable Captcha System]]></value>
    </item>
    <item name="msg_start_drag">
        <value xml:lang="ko"><![CDATA[잠김 : 등록 버튼을 활성화하려면 위 버튼을 우측 끝까지 드래그하십시오.]]></value>
        <value xml:lang="en"><![CDATA[Locked : Form cannot be submited.]]></value>
    </item>  
    <item name="msg_end_drag">
        <value xml:lang="ko"><![CDATA[해제 : 등록 버튼이 활성화 되었습니다.]]></value>
        <value xml:lang="en"><![CDATA[Unlocked : Form can be submited.]]></value>
    </item>
    <item name="msg_qaptcha_key_not_exist">
        <value xml:lang="ko"><![CDATA[캡챠키를 생성할 수 있는 OS 환경이 아닙니다.]]></value>
        <value xml:lang="en"><![CDATA[Capable of generating a Qaptcha key is not the OS environment.]]></value>
    </item>

lang.xml 파일을 열고 맨하단에 캡챠에서 사용할 언어 item을 추가합니다.



2. 회원가입 스킨 파일 수정


./modules/member/skins/default/signup_form.html
1
2
3
4
5
6
7
8
9
<load target="../../tpl/js/signup_check.js" />
<!--// datepicker javascript plugin load -->
<!--%load_js_plugin("ui")-->
<!--%load_js_plugin("ui.datepicker")-->
<!--// QapTcha Load -->
<load target="./css/qaptcha.css" />
<load target="./js/QapTcha.jquery.js" />
<load target="./js/jquery.ui.touch.js" />
<include target="./common_header.html" />

회원가입 폼을 출력하는 signup_form.html 을 열고 4번라인 아래부터 헤더 include문 위까지

캡챠가 사용할 css, js파일을 로드하는 구문을 추가합니다.  


./modules/member/skins/default/signup_form.html
65
66
67
68
69
70
71
72
73
74
75
76
77
<!--// QapTcha Drag Start -->
        <div class="control-group">
            <div class="control-label"><em style="color:red">*</em> {$lang->draggable_qaptcha}</div>
            <div class="controls" style="padding-top:5px">
                <div class="QapTcha"></div>
            </div>
        </div>
        <!--// QapTcha Drag End-->
        <div class="btnArea" style="border-top:1px solid #ccc;padding-top:10px">
            <input type="submit" value="{$lang->cmd_registration}" class="btn btn-inverse pull-right" />
            <a href="{getUrl('act','','member_srl','')}" class="btn pull-left">{$lang->cmd_cancel}</a>
        </div>
    </form>

폼 안에 캡챠 드래그 버튼을 추가하는 태그를 위와 같이 추가합니다.

드래그 버튼은 폼 전송 버튼 바로 위에 위치하도록 만듭니다.


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<script>
jQuery(function($){
    // label for setup
    $('.control-label[for]').each(function(){
        var $this = $(this);
        if($this.attr('for') == ''){
            $this.attr('for', $this.next().children(':visible:first').attr('id'));
        }
    });
});
(function($){
    $(function(){
        var option = { changeMonth: true, changeYear: true, gotoCurrent: false,yearRange:'-100:+10', dateFormat:'yy-mm-dd', onSelect:function(){
            $(this).prev('input[type="hidden"]').val(this.value.replace(/-/g,""))}
        };
        $.extend(option,$.datepicker.regional['{$lang_type}']);
        $(".inputDate").datepicker(option);
        $(".dateRemover").click(function() {
            $(this).prevAll('input').val('');
            return false;});
    });
})(jQuery);
jQuery(function($){
    // QapTcha Language
    var start_drag = '{$lang->msg_start_drag}';
    var end_drag = '{$lang->msg_end_drag}';
    $('.QapTcha').QapTcha({ txtLock: start_drag, txtUnlock: end_drag });
    // jQuery.ui.touch Plugin
    $('.Slider').addTouch();
});
</script>

맨하단 스크립트에는 폼라벨과 생년월일 입력(팝업 캘린더)을 위한 jquery 스크립트가 이미 들어 있습니다.

캽차에서 사용할 언어와 터치 동작을 위한 함수 호출 구문을 위와 같이 스크립트 안에 추가합니다.



3. 플러그인, CSS, 버튼 이미지 업로드


./modules/member/skins/default/js/QapTcha.jquery.js

./modules/member/skins/default/js/jquery.ui.touch.js

./modules/member/skins/default/css/qaptcha.css

./modules/member/skins/default/css/btn_qaptcha.jpg


위 경로를 따라 jQuery 플러그인 파일, CSS 파일, 버튼 이미지를 업로드합니다.



4. 액션 추가


./modules/member/conf/module.xml
71
72
73
<action name="procMemberResetAuthMail" type="controller" ruleset="resetAuthMail" standalone="true" />
<action name="procMemberSpammerManage" type="controller" standalone="true" />
<action name="setQapTchaSession" type="controller" standalone="true" /> <!--// QapTcha Session creation -->
72번 라인 다음 줄, Admin 액션이 시작되는 바로 윗줄에 위와 같이 캡챠가 사용할 setQapTchaSession 액션을 추가합니다.



5. 컨트롤러 수정


./modules/member/member.controller.php
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/***** QapTcha 세션 세팅 ****************************************************/
    function setQapTchaSession() 
    {
        $qaptcha_response_error = true;
 
        $response_action = Context::get('response_action');
        $qaptcha_key = Context::get('qaptcha_key');
 
        // qaptcha_key가 없다면
        if(!$qaptcha_keyreturn new Object(-1, 'msg_qaptcha_key_not_exist');
 
        if(isset($response_action) && isset($qaptcha_key)) 
        {
            $_SESSION['qaptcha_key'] = false;
            if(htmlentities($response_action, ENT_QUOTES, 'UTF-8') == 'qaptcha'
            {
                $_SESSION['qaptcha_key'] = $qaptcha_key;
                $qaptcha_response_error = false;
            }
        }
 
        $this->add('qaptcha_response_error'$qaptcha_response_error);
    }
    /***************************************************************************/
 
    /**
     * Join Membership
     *
     * @return void|Object (void : success, Object : fail)
     */
    function procMemberInsert()
    {

member.controller.php 파일을 열면 250번 라인에서 회원가입을 실행하는 procMemberInsert() 메소드가 있습니다.

그 윗부분에 위와 같이 캡챠 세션을 세팅하는 소스코드를 복사하여 붙여넣기 합니다.

회원가입 폼에서 캡챠 버튼을 드래그하면 AJAX 방식으로 위 액션이 실행되고 생성된 키값을 받아 $_SESSION에 세팅해 두는 기능을 수행합니다. 실제로 폼이 전송되면 전송된 폼 안에서 이 키값으로 속성(name)을 찾고 값(value)이 비어 있는지를 확인할 것입니다. 드래깅 했을때는 속성과 값이 모두 채워져 전송됩니다.



./modules/member/member.controller.php
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/**
     * Join Membership
     *
     * @return void|Object (void : success, Object : fail)
     */
    function procMemberInsert()
    {
        if (Context::getRequestMethod () == "GET"return new Object (-1, "msg_invalid_request");
        /***** QapTcha 세션 확인 ******************************************************/
        if(!isset($_SESSION['qaptcha_key'])) return new Object (-1, "msg_signup_disabled");
 
        if(isset($_SESSION['qaptcha_key']) && !empty($_SESSION['qaptcha_key'])) 
        {
 
            $QapTchaInput $_SESSION['qaptcha_key'];
            $QapTchaInputValue $_POST[''.$QapTchaInput.''];
            if(isset($QapTchaInputValue) && !empty($QapTchaInputValue))
            {
                unset($_SESSION['qaptcha_key']);
                return new Object (-1, "msg_signup_disabled");
            }
        }
        /*****************************************************************************/
        $oMemberModel = &getModel ('member');
        $config $oMemberModel->getMemberConfig();

procMemberInsert() 메소드 안에서는 요청방법을 확인하는 코드 다음줄에 위 소스코드를 복사하여 붙여넣기 합니다.

캡챠 드래깅 없이 호출되었거나, 웹브라우저를 닫고 나간 경우 일정시간이 지난후에는 세션이 자동으로 삭제되기 때문에 세션값이 없다면 하위 로직은 진행되지 않을 것입니다. 만약 세션은 있지만 이전에 저장해둔 세션값으로 전송된 폼의 속성(name)값을 찾았을때 값이 여전히 채워져있다면 마찬가지로 로직은 멈추게 됩니다. 전송된 속성(name)값이 이전에 저장된 세션과 달라도 멈춥니다. qaptcha_key 값은 뷰에서 버튼이 드래깅 될때마다 매번 다른 키값으로 생성되고 서버에서는 그 값을 받아 세션에 다시 저장합니다.


[중요]

만약 자바스크립트가 지원되지 않은 OS 환경에서는

위와 같은 드래그 방식의 캡챠는 정상적으로 동작하지 않습니다.


XE 1.7.5에 포함되어 있는 Captcha Member 애드온을 켜면 바로 다음 로직에서 트리거가 작동하기 때문에 간섭받지 않습니다. QapTcha를 애드온 또는 트리거로 활용하지 않은 것은 컨트롤러 로직 안에 직접 포함시키기 위한 것이고 애드온이나 트리거 역시 네이티브 소스코드로 동작한다고는 하지만 보안에 따른 검증은 별개의 문제이기 때문에 직접 구현하고자 시도하였습니다. 옵션의 설정은 원문사이트를 참고하세요.


DEMO : http://xeschool.cafe24.com/

http://www.myjqueryplugins.com/jquery-plugin/qaptcha


※ 첨부파일에는 같은 내용으로 수정된 회원정보수정 폼(modify_info.html)과 모바일(m.skins)을 위한 수정파일도 포함되어 있습니다. (생년월일 입력/삭제 등 수정된 파일을 포함합니다.)


제목 글쓴이 날짜
포항마사지【오피사이트.NET】포항스웨디시 포항안마 포항1인샵 songkangkong767 2025.02.24
안산오피 안산출장안마 ⦑오피쓰주소.COM⦒ 안산OP 안산오피 안산오피 koykoyah 2025.02.24
인천안마【출장안마사이트.COM】인천안마 인천 안마 인천안마 songkangkong767 2025.02.24
연신내오피 연신내오피 ⦑출장안마사이트.COM⦒ 연신내OP 연신내스파 연신내오피 koykoyah 2025.02.24
부평안마【오피사이트.NET】부평스웨디시 부평마사지 부평1인샵 songkangkong767 2025.02.24
제주오피 ⦑오피쓰주소.COM⦒ 제주OP 제주오피 제주출장샵 제주오피 koykoyah 2025.02.24
신림안마【오피.CLUB】신림마사지 신림스웨디시 신림1인샵 songkangkong767 2025.02.24
제주도오피 ⦑오피쓰주소.COM⦒ 제주도오피 제주도OP 제주도건마 제주도오피 koykoyah 2025.02.24
충주1인샵【오피쓰주소.COM】충주안마 충주마사지 충주스웨디시 songkangkong767 2025.02.24
답십리오피 답십리출장안마 ⦑출장마사지안내.COM⦒ 답십리OP 답십리오피 답십리오피 koykoyah 2025.02.24
연신내스웨디시【오피.CLUB】연신내 스웨디시 연신내스웨디시 연신내스웨디시 songkangkong767 2025.02.24
압구정오피 압구정OP ⦑오피쓰주소.COM⦒ 압구정휴게텔 압구정오피 압구정오피 koykoyah 2025.02.24
동대문오피 동대문OP ⦑오피사이트.NET⦒ 동대문휴게텔 동대문오피 동대문오피 koykoyah 2025.02.24
가락오피 ⦑오피사이트.NET⦒ 가락OP 가락오피 가락출장샵 가락오피 koykoyah 2025.02.24
전주오피 ⦑오피쓰.COM⦒ 전주오피 전주출장마사지 전주오피 전주OP koykoyah 2025.02.24
청주스웨디시【오피쓰주소.COM】청주 스웨디시 청주스웨디시 청주스웨디시 songkangkong767 2025.02.24
울산1인샵【출장안마사이트.COM】울산안마 울산스웨디시 울산마사지 songkangkong767 2025.02.24
부천오피 부천OP ⦑오피쓰.COM⦒ 부천휴게텔 부천오피 부천오피 koykoyah 2025.02.24
동두천오피 동두천출장안마 ⦑오피.CLUB⦒ 동두천OP 동두천오피 동두천오피 koykoyah 2025.02.24
강서오피 ⦑오피.CLUB⦒ 강서마사지 강서오피 강서오피 강서OP koykoyah 2025.02.24