테스트 사이트 - 개발 중인 베타 버전입니다

스팸 게시물 / 회원가입 방지를 위한 코드

· 5개월 전 · 536 · 6

 

[주] 이후 강좌수정내용의 업데이트가 안될수 있습니다.

본 강좌의 최신업데이트는 https://www.happyjung.com/lecture/2910 에서 확인가능합니다.

가급적 동일한 내용을 유지하려고 노력하지만, 우선 작업은 위 링크입니다.

 

 

그누보드 스팸 방지를 위한 여러가지 방법들이 존재합니다
다양한 방법에 대한 것을 실제 테스트를 통해 확인된 사항을 정리합니다


1. 스킨에 아래 파일에 내용 추가
글 쓰기  skin/board/스킨명/write.skin.php
댓글 쓰기  skin/board/스킨명/view_comment.skin.php

<input type="hidden" name="w_time" value="<?php echo time(); ?>">



2. 스킨에 아래 파일 생성 (파일이 있는 경우 내용 추가)
글 저장  skin/board/스킨명/write_update.head.skin.php
댓글 저장  skin/board/스킨명/write_comment_update.head.skin.php
[code]
<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가

if (!$is_admin && ($w == '' || $w == 'r')) {
    
    // 1. 글쓰기 페이지에 머문 시간을 비교해서 스팸여부 확인 (최소 10초))
    /*
    // view_comment.skin.php 에 아래 내용 추가
    <input type="hidden" name="w_time" value="<?php echo time(); ?>">
    */
    $w_time = isset($_POST['w_time']) ? (int)$_POST['w_time'] : time();
    $spam_time_check = time() - $w_time;

    if ($spam_time_check < 10 || $spam_time_check > 86400) {
        alert('너무 빠른 글쓰기는 건강에 좋지 않습니다. 10초의 여유를 갖으세요.');
    }


    // 2. 작성자 이름이 영어로만 구성된 경우 스팸글로 차단
    if ($member['mb_id']) {
        $wr_name = addslashes(clean_xss_tags($board['bo_use_name'] ? $member['mb_name'] : $member['mb_nick']));
    } else {
        // 비회원의 경우 이름이 누락되는 경우가 있음
        $wr_name = clean_xss_tags(trim($_POST['wr_name']));
    }
    if (isset($wr_name) && !preg_match('/[가-힣]/u', $wr_name)) {
        alert("이름은 반드시 한글을 포함해야 합니다.");
    }


    // 3. 같은 IP에서 2분 이내에 연속으로 글을 작성 방지
    $client_ip = $_SERVER['REMOTE_ADDR'];
    $now = G5_TIME_YMDHIS; // 현재 시간
    $check_interval_min = 2; // 분
    $check_interval_sec = $check_interval_min * 60; // 초

    $sql = "SELECT wr_datetime 
            FROM `{$write_table}` 
            WHERE wr_ip = '{$client_ip}' 
              AND wr_is_comment = 1 
            ORDER BY wr_datetime DESC 
            LIMIT 1";
    $row = sql_fetch($sql);

    if ($row['wr_datetime']) {
        $last_time = strtotime($row['wr_datetime']);
        $current_time = strtotime($now);

        if (($current_time - $last_time) < $check_interval_sec) {
            alert("같은 IP에서 {$check_interval_min}분 이내에 연속으로 댓글을 작성할 수 없습니다.");
        }
    }


    // 4. 특정 이메일 글쓰기 차단
    $blocked_emails = ['1@1.com', 'test@test.com', 'spam@example.com'];

    if (isset($member['mb_email']) && in_array($member['mb_email'], $blocked_emails)) {
        alert("해당 이메일 계정으로는 글을 작성할 수 없습니다.");
    }

    if (!$member['mb_id'] && isset($_POST['wr_email']) && in_array($_POST['wr_email'], $blocked_emails)) {
        alert("해당 이메일 계정으로는 글을 작성할 수 없습니다.");
    }
    
    
    // 5. 특정 단어 필터링 (금지어)
    $banned_words = ['viagra', 'casino', 'sex']; 
    foreach ($banned_words as $word) {
        if (stripos($_POST['wr_content'], $word) !== false) {
            alert("금지된 단어가 포함되어 있어 등록할 수 없습니다.");
        }
    }
    
    
    // 6. 글자 수가 너무 짧은 경우도 제한
    if (mb_strlen(strip_tags($_POST['wr_content']), 'UTF-8') < 5) {
        alert("내용은 5자 이상 입력해주세요.");
    }
}



3. 회원가입시 이름, 닉네임이 모두 영어 인경우 회원 저장안하기
스킨/member/basic/register_form_update.head.skin.php 생성하고 아래 내용 추가

<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가

if (!function_exists('str_ends_with')) {
    /**
     * Polyfill for PHP < 8.0
     */
    function str_ends_with($haystack, $needle) {
        if ($needle === '') return true;
        $len = strlen($needle);
        return substr($haystack, -$len) === $needle;
    }
}
// 가입자 이름, 닉네임이 모두 영어인 경우 회원 레벨 1로 변경
// 이름/닉네임에 한글이 없는 경우 → 회원레벨 1로 강등
$is_name_eng_only = (isset($mb['mb_name']) && !preg_match('/[가-힣]/u', $mb['mb_name']));
$is_nick_eng_only = (isset($mb['mb_nick']) && !preg_match('/[가-힣]/u', $mb['mb_nick']));
if ($is_name_eng_only && $is_nick_eng_only) {
    goto_url(G5_URL);
}


// 동일 IP로 차단된 회원이 존재하는지 검사
$join_ip = $_SERVER['REMOTE_ADDR'];
$ip_blocked = sql_fetch("SELECT COUNT(*) as cnt FROM `{$g5['member_table']}` WHERE mb_intercept_date <> '' AND mb_ip = '{$join_ip}'");
if ($ip_blocked['cnt'] > 0) {
    goto_url(G5_URL);
}

// 차단할 이메일 도메인 목록
$blocked_domains = ['@qq.com', '@aa.com', '@spamdomain.net'];
$email = strtolower(trim($mb['mb_email'] ?? ''));

if ($email) {
    foreach ($blocked_domains as $domain) {
        if (str_ends_with($email, strtolower($domain))) {
            goto_url(G5_URL); // 차단 도메인일 경우 즉시 이동
        }
    }
}
[/code]


4. 회원가입시 이름, 닉네임이 모두 영어 인경우 회원레벨 1로 만들기
스킨/member/basic/register_form_update.tail.skin.php 생성하고 아래 내용 추가
[code]
<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가

// 가입자 이름, 닉네임이 모두 영어인 경우 회원 레벨 1로 변경
// 이름/닉네임에 한글이 없는 경우 → 회원레벨 1로 강등
$is_name_eng_only = (isset($mb['mb_name']) && !preg_match('/[가-힣]/u', $mb['mb_name']));
$is_nick_eng_only = (isset($mb['mb_nick']) && !preg_match('/[가-힣]/u', $mb['mb_nick']));
if ($is_name_eng_only && $is_nick_eng_only) {
    sql_query("UPDATE `{$g5['member_table']}` SET mb_level = '1' WHERE mb_id = '{$mb['mb_id']}'");
}

// 동일 IP로 차단된 회원이 존재하는지 검사
$join_ip = $_SERVER['REMOTE_ADDR'];
$ip_blocked = sql_fetch("SELECT COUNT(*) as cnt FROM `{$g5['member_table']}` WHERE mb_intercept_date <> '' AND mb_ip = '{$join_ip}'");
if ($ip_blocked['cnt'] > 0) {
    sql_query("UPDATE `{$g5['member_table']}` SET mb_level = '1' WHERE mb_id = '{$mb['mb_id']}'");
}
[/code]


5. 메인 페이지 세션이 없는 경우 글쓰기 금지
extend / spam_deny.php 생성하고 추가
검증이 필요해서 삭제


6. 해외 아이피 글쓰기 차단
데모 : https://www.happyjung.com/demo/php/x-real_ip.php

mobile / skin / board / basic / write_update.head.skin.php
skin / board / basic / write_update.head.skin.php

검증이 필요해서 삭제

 


7. hook 이용 자동으로 글 쓰는 스팸 막기 ( 그누보드 5.4.3 이상에만 사용 가능 )
extend / spam.write.ban.extend.php 파일 생성후 아래 내용 저장

검증이 필요해서 삭제



참고자료
https://sir.kr/g5_tip/14663
https://sir.kr/g5_tip/16141
https://sir.kr/qa/468232?#answer_468235
https://sir.kr/g5_plugin/10184
https://sir.kr/qa/391725#answer_391740

댓글 작성

댓글을 작성하시려면 로그인이 필요합니다.

로그인하기

댓글 6개

5개월 전

좋은 팁 감사 합니다.

5개월 전
적용해 보겠습니다. 감사합니다 ^^
5개월 전

좋은팁 감사합니다.

5개월 전

필요한 기능 감사합니다

5개월 전

감사합니다

감사합니다.

게시글 목록

번호 제목
24149
24140
24133
24125
24119
24109
24105
24101
24093
24089
24077
24074
24071
24070
24067
24056
24050
24046
24043
24040
24037
24036
24035
24034
24021
24017
24005
24002
23990
23980