그누보드 [G4/G5] 스팸 게시물 / 회원가입 방지를 위한 코드
페이지 정보

본문
그누보드 스팸 방지를 위한 여러가지 방법들이 존재합니다
다양한 방법에 대한 것을 실제 테스트를 통해 확인된 사항을 정리합니다
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
<?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); // 차단 도메인일 경우 즉시 이동
}
}
}
4. 회원가입시 이름, 닉네임이 모두 영어 인경우 회원레벨 1로 만들기
스킨/member/basic/register_form_update.tail.skin.php 생성하고 아래 내용 추가
<?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']}'");
}
5. 메인 페이지 세션이 없는 경우 글쓰기 금지
extend / spam_deny.php 생성하고 추가
<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
// 메인 페이지를 방문하지 않고 글작성을 시도하는 경우 차단
$spam_deny_checkurl = basename($_SERVER['SCRIPT_NAME']);
if ($spam_deny_checkurl == 'index.php') {
set_session('ss_spam_index_token', true);
}
if ($spam_deny_checkurl == 'write_update.php' || $spam_deny_checkurl == 'write_comment_update.php') {
if (!get_session('ss_spam_index_token')) {
die('허용되지 않은 접근입니다.');
}
}
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
<?php
if (!defined("_GNUBOARD_")) exit;
// 해외아이피 글쓰기 차단
$client_ip = isset($_SERVER['HTTP_CLIENT_IP'])?$_SERVER['HTTP_CLIENT_IP']:isset($_SERVER['HTTP_X_FORWARDED_FOR'])?$_SERVER['HTTP_X_FORWARDED_FOR']:$_SERVER['REMOTE_ADDR'];
$details = json_decode(file_get_contents("https://ipinfo.io/{$client_ip}/json"));
if($details->country != "KR"){
alert("Only Korea Accept");
exit();
}
7. hook 이용 자동으로 글 쓰는 스팸 막기 ( 그누보드 5.4.3 이상에만 사용 가능 )
extend / spam.write.ban.extend.php 파일 생성후 아래 내용 저장
<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
// hook 이용 자동으로 글 쓰는 스팸 막기
if(!defined('CHECK_WRITEPAGE_SPAM_INPUT_NAME')){
// 아래 상수값 영문소문자+숫자로 되어 있는 부분을 반드시 영문소문자+숫자로 마음대로 변경해주세요.
define('CHECK_WRITEPAGE_SPAM_INPUT_NAME', 'abc123def456ghi');
}
if(!defined('CHECK_WRITEPAGE_SPAM_INPUT_VALUE')){
// 아래 상수값 한글로 되어 있는 부분을 반드시 한글로 마음대로 변경해주세요.
define('CHECK_WRITEPAGE_SPAM_INPUT_VALUE', '대한민국사랑해');
}
add_event('bbs_write', 'g5_check_spam_write_page', 1, 2);
function g5_check_spam_write_page($board, $wr_id){
add_event('tail_sub', 'g5_add_script_write_page_input');
}
function g5_add_script_write_page_input(){
?>
<script>
jQuery(function ($) {
$('<input>').attr({
type: 'hidden',
name: '<?php echo CHECK_WRITEPAGE_SPAM_INPUT_NAME; ?>',
value: '<?php echo CHECK_WRITEPAGE_SPAM_INPUT_VALUE; ?>'
}).appendTo('form[name=fwrite]');
});
</script>
<?php
}
add_event('write_update_before', 'g5_check_spam_write_update_before', 1, 2);
function g5_check_spam_write_update_before($board, $wr_id){
if( isset($_POST[CHECK_WRITEPAGE_SPAM_INPUT_NAME]) && $_POST[CHECK_WRITEPAGE_SPAM_INPUT_NAME] === CHECK_WRITEPAGE_SPAM_INPUT_VALUE ){
return;
} else {
alert("스팸 싫어요");
exit();
}
}
참고자료
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
다양한 방법에 대한 것을 실제 테스트를 통해 확인된 사항을 정리합니다
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
<?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); // 차단 도메인일 경우 즉시 이동
}
}
}
4. 회원가입시 이름, 닉네임이 모두 영어 인경우 회원레벨 1로 만들기
스킨/member/basic/register_form_update.tail.skin.php 생성하고 아래 내용 추가
<?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']}'");
}
5. 메인 페이지 세션이 없는 경우 글쓰기 금지
extend / spam_deny.php 생성하고 추가
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
// 메인 페이지를 방문하지 않고 글작성을 시도하는 경우 차단
$spam_deny_checkurl = basename($_SERVER['SCRIPT_NAME']);
if ($spam_deny_checkurl == 'index.php') {
set_session('ss_spam_index_token', true);
}
if ($spam_deny_checkurl == 'write_update.php' || $spam_deny_checkurl == 'write_comment_update.php') {
if (!get_session('ss_spam_index_token')) {
die('허용되지 않은 접근입니다.');
}
}
6. 해외 아이피 글쓰기 차단
데모 : https://www.happyjung.com/demo/php/x-real_ip.php
skin / board / basic / write_update.head.skin.php
<?php
if (!defined("_GNUBOARD_")) exit;
// 해외아이피 글쓰기 차단
$client_ip = isset($_SERVER['HTTP_CLIENT_IP'])?$_SERVER['HTTP_CLIENT_IP']:isset($_SERVER['HTTP_X_FORWARDED_FOR'])?$_SERVER['HTTP_X_FORWARDED_FOR']:$_SERVER['REMOTE_ADDR'];
$details = json_decode(file_get_contents("https://ipinfo.io/{$client_ip}/json"));
if($details->country != "KR"){
alert("Only Korea Accept");
exit();
}
7. hook 이용 자동으로 글 쓰는 스팸 막기 ( 그누보드 5.4.3 이상에만 사용 가능 )
extend / spam.write.ban.extend.php 파일 생성후 아래 내용 저장
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
// hook 이용 자동으로 글 쓰는 스팸 막기
if(!defined('CHECK_WRITEPAGE_SPAM_INPUT_NAME')){
// 아래 상수값 영문소문자+숫자로 되어 있는 부분을 반드시 영문소문자+숫자로 마음대로 변경해주세요.
define('CHECK_WRITEPAGE_SPAM_INPUT_NAME', 'abc123def456ghi');
}
if(!defined('CHECK_WRITEPAGE_SPAM_INPUT_VALUE')){
// 아래 상수값 한글로 되어 있는 부분을 반드시 한글로 마음대로 변경해주세요.
define('CHECK_WRITEPAGE_SPAM_INPUT_VALUE', '대한민국사랑해');
}
add_event('bbs_write', 'g5_check_spam_write_page', 1, 2);
function g5_check_spam_write_page($board, $wr_id){
add_event('tail_sub', 'g5_add_script_write_page_input');
}
function g5_add_script_write_page_input(){
?>
<script>
jQuery(function ($) {
$('<input>').attr({
type: 'hidden',
name: '<?php echo CHECK_WRITEPAGE_SPAM_INPUT_NAME; ?>',
value: '<?php echo CHECK_WRITEPAGE_SPAM_INPUT_VALUE; ?>'
}).appendTo('form[name=fwrite]');
});
</script>
<?php
}
add_event('write_update_before', 'g5_check_spam_write_update_before', 1, 2);
function g5_check_spam_write_update_before($board, $wr_id){
if( isset($_POST[CHECK_WRITEPAGE_SPAM_INPUT_NAME]) && $_POST[CHECK_WRITEPAGE_SPAM_INPUT_NAME] === CHECK_WRITEPAGE_SPAM_INPUT_VALUE ){
return;
} else {
alert("스팸 싫어요");
exit();
}
}
참고자료
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
댓글목록
등록된 댓글이 없습니다.