js 유효성 검사 템플릿 (+SQL injection)
$('#submitBtn').click(function() {
var frm = document.frm2;
/* 유효성 체크 start */
if (!validationChk()) return;
/* 유효성 체크 end */
frm.action = "";
frm.method = "POST";
frm.submit();
});
var lengthFlag = true;
function validationChk(){
var frm = document.frm2;
var title = frm.title;
var phone1 = frm.phone1;
var phone2 = frm.phone2;
var phone3 = frm.phone3;
var email = frm.email;
var problem = frm.problem;
var improvement = frm.improvement;
var benefit = frm.benefit;
var detail = frm.detail;
var agree = frm.agree;
var email_pattern = /^[A-Za-z0-9_\.\-]+@[A-Za-z0-9\-]+\.[A-Za-z0-9\-]+/; //(알파벳,숫자)@(알파벳,숫자).(알파벳,숫자)
if (title.value.trim().length == "") {
alert("제목을 입력하세요.");
title.focus();
return false;
}
if (phone1.value.trim().length == "") {
alert("휴대폰 번호를 입력하세요.");
phone1.focus();
return false;
}
if (phone2.value.trim().length == "") {
alert("휴대폰 번호를 입력하세요.");
phone2.focus();
return false;
}
if (phone3.value.trim().length == "") {
alert("휴대폰 번호를 입력하세요.");
phone3.focus();
return false;
}
if (email.value.trim().length == "") {
alert("이메일을 입력하세요.");
email.focus();
return false;
}
if(email_pattern.test(email.value)==false){
alert("이메일 주소가 올바르지 않습니다.");
email.focus();
return false;
}
if (problem.value.trim().length == "") {
alert("현황 및 문제점을 입력하세요.");
problem.focus();
return false;
}
if (improvement.value.trim().length == "") {
alert("개선방안을 입력하세요.");
improvement.focus();
return false;
}
if (benefit.value.trim().length == "") {
alert("기대효과를 입력하세요.");
benefit.focus();
return false;
}
if (detail.value.trim().length == "") {
alert("세부사항을 입력하세요.");
detail.focus();
return false;
}
if (!lengthFlag) {
alert("글자수가 허용범위를 넘었습니다.");
return false;
}
if (!agree.checked) { //체크박스 미체크시
alert("약관 동의를 체크하세요.");
agree.focus();
return false;
}
/* check or convert value for security */
if (!securityChk(title, "제목", 1)) {
title.focus();
return false;
}
if (!securityChk(problem, "현황 및 문제점",1)) {
problem.focus();
return false;
}
if (!securityChk(improvement, "개선방안",1)) {
improvement.focus();
return false;
}
if (!securityChk(benefit, "기대효과",1)) {
benefit.focus();
return false;
}
if (!securityChk(detail, "세부사항",1)) {
detail.focus();
return false;
}
/* check or convert value for security */
/* input and textarea value LTRIM RTRIM */
var inputLength = document.querySelectorAll('#frm2 input[type="text"]');
var textareaLength = document.querySelectorAll('#frm2 textarea');
for (var i = 0; i < inputLength.length; i++) {
inputLength[i].value = inputLength[i].value.replace(/^\s+/,"");
inputLength[i].value = inputLength[i].value.replace(/\s+$/,"");
}
for (var i = 0; i < textareaLength.length; i++) {
textareaLength[i].value = textareaLength[i].value.replace(/^\s+/,"");
textareaLength[i].value = textareaLength[i].value.replace(/\s+$/,"");
}
return true;
}
//textarea 바이트 수 체크하는 함수
function fn_checkByte(obj){
// textarea 에 onkeyup="fn_checkByte(this)" 추가
// textarea 태그 아래에 <sup>(<span class="nowByte">0</span>/3500bytes)</sup> 추가
const maxByte = 3500; //최대 3500바이트
const text_val = obj.value; //입력한 문자
const text_len = text_val.length; //입력한 문자수
var totalByte=0;
for(let i=0; i<text_len; i++){
const each_char = text_val.charAt(i);
const uni_char = escape(each_char); //유니코드 형식으로 변환
if(uni_char.length>4){
// 한글 : 3Byte
totalByte += 3;
}else{
// 영문,숫자,특수문자 : 1Byte
totalByte += 1;
}
}
var nowByteClass = document.getElementsByClassName('nowByte');
var textarea = document.getElementsByTagName('textarea');
var index = 0;
for (var i = 0; i < textarea.length; i++) {
if (textarea[i] == obj) index = i;
}
if(totalByte > maxByte){
alert('최대 3500Byte까지만 입력가능합니다.');
nowByteClass[index].innerText = totalByte;
nowByteClass[index].style.color = "red";
lengthFlag = false;
}else{
nowByteClass[index].innerText = totalByte;
nowByteClass[index].style.color = "green";
lengthFlag = true;
}
}
/* 웹 취약점 보완 */
function securityChk(obj, target, level){
let keyword = obj.value.trim();
if (keyword.length > 0) {
console.log('before attack defense ' + target + ' keyword transformation : ' + keyword);
/* XSS attack defense start*/
let expText = /[&<>"'/()*]/g; //특수문자 제거
if (expText.test(keyword)) {
//alert(target + "에 [SQL Injection] 특수문자를 입력 할 수 없습니다.");
//keyword = keyword.split(expText).join("");
if (level == undefined || level == 0) {
keyword = keyword.replaceAll(expText,".");
obj.value = keyword;
}else if (level != undefined && level == 1) {
var escapeHtmlMap = {
"&" : "&",
"<" : "<",
">" : ">",
'"' : '"',
"'" : ''',
"/" : '/',
"(" : '(',
")" : ')',
"*" : ""
/* "script" : "",
"iframe" : "",
"embed" : "" */
};
String.prototype.escapeHTML = function() {
return String(this).replaceAll(expText, function(s) {
return escapeHtmlMap[s];
});
};
keyword = keyword.escapeHTML();
}
obj.value = keyword;
console.log('after [XSS] attack defense ' + target + ' keyword transformation : ' + keyword);
}
/* XSS attack defense end*/
/* SQL INJECTION attack defense start*/
let sqlArray = new Array( //특정문자열(sql예약어의 앞뒤공백포함) 제거
//sql 예약어
"OR",
"SELECT",
"INSERT",
"DELETE",
"UPDATE",
"CREATE",
"DROP",
"EXEC",
"UNION",
"FETCH",
"DECLARE",
"TRUNCATE"
);
let regex;
for (let i = 0; i < sqlArray.length; i++) {
regex = new RegExp(sqlArray[i], "gi");
if (regex.test(keyword)) {
keyword = keyword.replace(regex, ".");
obj.value = keyword;
console.log('after [SQL Injection] attack defense ' + target + ' keyword transformation : ' + keyword);
//alert(target + '에 [SQL Injection] "' + sqlArray[i] + '"와(과) 같은 특정문자열로 검색할 수 없습니다.');
//return false;
}
}
/* SQL INJECTION attack defense end */
}
return true;
}
//날짜 유효성 체크 (윤달 포함)
function dateFormatChk(vDate) {
var vValue = vDate;
var vValue_Num = vValue.replace(/[^0-9]/g, ""); //숫자를 제외한 나머지는 예외처리 합니다.
/* if (_fnToNull(vValue_Num) == "") {
alert("날짜를 입력 해 주세요.");
return false;
} */
//8자리가 아닌 경우 false
if (vValue_Num.trim().length != 0 && vValue_Num.trim().length != 8) {
alert("날짜를 20200101 or 2020-01-01 형식으로 입력 해 주세요.");
return false;
}
//8자리의 yyyymmdd를 원본 , 4자리 , 2자리 , 2자리로 변경해 주기 위한 패턴생성을 합니다.
var rxDatePattern = /^(\d{4})(\d{1,2})(\d{1,2})$/;
var dtArray = vValue_Num.match(rxDatePattern);
if (dtArray == null) return false;
//0번째는 원본 , 1번째는 yyyy(년) , 2번재는 mm(월) , 3번재는 dd(일) 입니다.
dtYear = dtArray[1];
dtMonth = dtArray[2];
dtDay = dtArray[3];
//yyyymmdd 체크
if (dtMonth < 1 || dtMonth > 12) {
alert("존재하지 않은 월을 입력하셨습니다. 다시 한번 확인 해주세요");
return false;
}
else if (dtDay < 1 || dtDay > 31) {
alert("존재하지 않은 일을 입력하셨습니다. 다시 한번 확인 해주세요");
return false;
}
else if ((dtMonth == 4 || dtMonth == 6 || dtMonth == 9 || dtMonth == 11) && dtDay == 31) {
alert("존재하지 않은 일을 입력하셨습니다. 다시 한번 확인 해주세요");
return false;
}
else if (dtMonth == 2) {
var isleap = (dtYear % 4 == 0 && (dtYear % 100 != 0 || dtYear % 400 == 0));
if (dtDay > 29 || (dtDay == 29 && !isleap)) {
alert("존재하지 않은 일을 입력하셨습니다. 다시 한번 확인 해주세요");
return false;
}
}
return true;
}