Fingerprint.js 라이브러리

https://github.com/Valve/fingerprintjs

 

사용자의 브라우저 버전을 표시할 수 있다.

- 웹 서버가 통신을 하는 과정에서 전송되는 기본정보

- 브라우저의 종류

- PC의 운영체제(OS)

- 쿠키 사용여부(브라우저 설정값) 정보

- 어도비 플래시(Adobe Flash), 자바 가상머신(Java Virtual Machine)을 통해 브라우저 기능을 지원하는 프로그램의 버전

- PC의 표준시

- 화면 해상도

- PC의 보유 글꼴 및 색상 등의 정보

- 그 외에도 여러가지.

 

이러한 정보들을 모아서 브라우저 지문이라고한다.

 

개인을 식별 할 수 있는 정보이기보다는 접속한 pc, 브라우저의 단순한 설정 정보를 말한다.

다양한 값을 가지기 때문에 로그인 시에 '2단계 인증'의 로직 중에 하나로 사용될 수 있다.

 

설정값 같은 경우에는 사용자 설정에 따라 수집된다.

예를 들어 pc의 표준시를 수집하는 경우 해당 pc의 국가나 사용자의 설정에 따라 24가지(-12~+12)의 값을 가질 수 있다.

 

쿠키는 보안설정 등의 변경으로 사용을 차단할 수 있지만, 브라우저 지문은 쿠키차단, IP주소를 숨기는 프록시를 사용하더라도 정보를 수집할 수 있다.

변경하려면 운영체제 및 소프트웨어의 정보를 변경해야 한다고한다.

 

특징을 잘 활용하면 쿠키 없이도 사용자를 식별할 수 있는 정보로 사용될 수 있다.



form validation

 

HTML

<div class="wrap">
    <form id="step-verification" class="form" active="" method="post">
        <div class="box">
            <h1 class="title">인증 절차</h1>
            <p class="desc">
              안전한 계정 사용을 위해 인증을 사용해 주세요.<br>
              인증은 아이디와 비밀번호 외 일회용 인증번호를 입력해야만
              로그인 할 수 있는 이중 보안 서비스입니다.<br>
              인증에 필요한 이메일을 등록하고 더욱 안전하게 계정을 보호하세요.
            </p>
            <p class="agree-area">
              <input id="agree" type="checkbox" />
              <label for="agree">
                인증을 위해 개인정보 수집 및 이용에 동의합니다.(필수)
              </label>              
          </p>
        </div>
        <div class="box">
          <h2 class="title">이메일 등록</h2>
          <p class="desc">        
            인증이 가능한 이메일 주소를 입력 후 인증번호 받기를 선택해 주세요.<br>
            입력한 이메일 주소로 발송된 인증번호를 입력하고 확인을 선택해 주세요.
          </p>
          <div class="email-area">
            <p>
              <label for="email">이메일</label>
              <input id="email" type="email" placeholder="이메일을 입력해주세요." />
              <button id="send-access-code" type="button">인증번호 받기</button>
            </p>
            <p>
              <label for="email-code">인증번호</label>
              <input id="email-code" type="text" placeholder="인증번호 입력(20분 이내)" />
            </p>
          </div>
        </div>
        <div>
          <button id="prev-page" type="button">이전으로</button>
          <button id="submit" type="button">확인</button>
        </div>
    </form>
</div>

 

 

 

 

CSS

.wrap{
  margin:0 auto;
  width:900px;
  background-color:#fff;
  border:1px solid #c4c4c4;
  box-shadow:3px 3px 10px rgba(0,0,0,0.3);
  font-size:16px; line-height:22px;
  color:#333;
}
.form{
  padding:30px;
}
.title{
  padding-bottom:20px; border-bottom:1px solid #c4c4c4;
}
.email-area label{
  display:block;
}
input[type=text],input[type=email]{
  width:50%; height:30px; text-indent:10px;
}
button{
  display:inline-block;
  height:35px;
  background-color:#fff;
  border:1px solid #c4c4c4; box-sizing:border-box;
}
button:hover{ background-color:#c4c4c4; color:#fff; }
.error-msg{ margin:0; color:red; font-size:12px; }

 

 

 

 

JS

var reg = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

// 이전으로 버튼
$('#prev-page').on('click', function(){ history.go(-1) });

// 유효성 검사
$('#send-access-code').on('click', function(){
  var $sendButton = $(this);
  var target = $(this).siblings('input[type=email]');
  accessCodeEmailValidate($sendButton,target);
});

$('#submit').on('click', function(){
  var $form = $('#step-verification');
  var validationResult = twoStepVaildate($form);
  
  if(validationResult){
    alert('성공!');
    // $form.submit();
  }
});

function accessCodeEmailValidate(triggerBtn,target){
  var $target = $(target);
  var targetVal = $(target).val();
  
  if(targetVal == ''){
    var errorMsg = '이메일 주소를 입력해주세요.';
    setErrorMsg($target,errorMsg);
    // alert('이메일 주소를 입력해주세요.');
    
  }else if( !reg.test(targetVal.toLowerCase()) ){
    var errorMsg = '잘못된 이메일 입니다.';
    setErrorMsg($target,errorMsg);
    
  }else{
    // api 호출 성공 시 btn 이름 변경
    $(k).siblings('#error').hide();
    if( $(triggerBtn).val() !== 'resend' ) $(triggerBtn).val('resend').text('인증번호 재발송');
  }
}

function setErrorMsg(target,errorMsg){
  var $target = $(target);
  var $targetParent = $target.parent();
  
  if($targetParent.find('#error').length < 1){
  	$targetParent.append('<p id="error" class="error-msg">'+ errorMsg +'</p>');
    
  }else{
  	$targetParent.find('#error').text(errorMsg).show();
  }
}

function twoStepVaildate(form){
  var validTarget = $(form).find('input');
  var failNum = 0;

  $.each(validTarget, function(i,k){
    // 개인 정보 동의
    if(k.type == 'checkbox') {
      var result = k.checked == true ? true : false;

      if (!result) {
        alert('2단계 인증 설정을 위한 개인정보 수집 및 이용에 동의해주세요.');
        failNum = failNum + 1;
      }
    }else if(k.type == 'text'){
      if(k.value == '') {
        failNum = failNum + 1;

        // error
        var errorMsg = '인증번호를 입력해 주세요.';
        setErrorMsg(k,errorMsg);

      }else{
          $(k).siblings('#error').hide();
      }

    }else if(k.type == 'email'){
      if(k.value == '') {
        failNum = failNum + 1;

        // error
        var errorMsg = '이메일 주소를 입력해주세요.';
        setErrorMsg(k,errorMsg);
      }else{
        if( !reg.test(k.value.toLowerCase()) ){
          failNum = failNum + 1;
          var errorMsg = '잘못된 이메일 입니다.';
          setErrorMsg(k,errorMsg);

        // error
        }else{
            $(k).siblings('#error').hide();
        }
      }
    }
  });

  if(failNum > 0) return false;
  else return true;
}

 

 

 

 
브라우저 히스토리 조작하기. (이전페이지, 다음페이지로 이동하기 방법)
window.history 객체에 대해 알아보자.
 
사용법
// 이전페이지로 history.go(-1)과 같다
history.back();

/*
	()안의 숫자로 페이지 이동 (-1)
    한페이지 이전 (-2)
    두페이지 이전 (1)
    한페이지 다음... history.back()보다 많이 사용
*/
history.go(); 

// 다음페이지로 history.go(1)와 같다.
history.forward(); 
 
 
나는 회원가입시 '이전으로' 버튼에서 사용 하였다.
브라우저 캐시가 남아있는 경우에 사용 가능하므로 새 페이지에서 불가능하다. 
혹은 url로 접근했을 경우 접근 전의 페이지로 이동한다. (브라우저 <- 이것과 같다.)

 

12byte를 초과하면 작성이 더는 안되게 해달라는 요구사항의 작업을 하였다.

코드

$(function(){ 

  // byte 체크 할 타겟 (input, textarea) 
  var $target = $('#name'); 

  // 값이 들어올때는 input, 커서가 들어오고 나갈때는 focus, focusout 
  $target.on('input focus focusout', function(){ 
  	bytesValidationChk($(this),12); // 12자까지 
  }); 

  // 체크 함수 
  function bytesValidationChk(target, maxByte) { 
	  // byte 체크 할 때 사용하는 함수들 선언 
    var returnVal = ''; 
    var currentLength = 0; 
    var codeByte = 0; 

    // input의 value 
    var targetVal = target.val(); 

    // input.length만큼 반복
    for(var i = 0; i < targetVal.length; i++){ 
      // 한글, 영문 등의 byte만큼 codeByte를 증가 
      var oneChar = escape(targetVal.charAt(i)); 

      // 한글 = 2byte 나머지 = 1byte 
      if(oneChar.length > 4) {
        codeByte += 2;
      }else {
        codeByte++;
      } 

      // length 체크 
      // codeByte 값이 내가 지정한 maxByte보다 작을 때 = currentLength 값을 1씩 증가 
      if(codeByte <= maxByte) {
        currentLength = i + 1;
      } 

    } 
  
    // codyByte가 내가 지정한 maxByte보다 커지면 
    if(codeByte >= maxByte){ 
      // currentLength만큼 targetVal를 잘라줘서 returnVal에 담아줌 
      returnVal = targetVal.substr(0, currentLength); // 한글로 12byte면 currentLength가 6임 

      // maxByte만큼 자른 returnVal를 target(input)에 value로 넣어줌 
      target.val(returnVal)	; 
    } 
  } // bytesValidationChk

});

여기서 문제가 된건....
ie8에서 input 이벤트가 적용되지 않는 것이었다.

(focus와 상관 없이 자판을 쳤을때 체크해서 복+붙 시에도 체크가 가능해야 했다)


따라서 key 이벤트를 당연히.. 넣어줬어야 했는데, 이렇게 되면 ctrl+a(전체선택)이 적용되지 않는다.
큰 문제는 아니지만, 누군가는 당연히 복+붙을 할터이니.. 이슈로 돌아올게 분명하다.

+ firefox 버전 61.0.1(2018.07.11 기준으로 최신)에서는 한글에 key 이벤트 적용이 안된다.
과거부터 있던 이슈라는데, 한글이 완성형 글자라서 그러느니 뭐라느니, 그래서 이때는 input태그를 필수로 사용했다.★

그래서 처음 해본게.
value값을 새로 넣는게 아니라 target.attr('maxlength')값에 접근해서 cuttrneLength값을 넣어주는 방법도 했는데,
이 방법은 복+붙 시에 완전히 적용되지 않더라...
(byte가 maxByte가 되면 maxlength 추가, 아니면 제거 형식)

그래서 그냥 ie8은 key이벤트를 추가하여.. ctrl+a를 포기하기로 했다. (이 이하는 아몰랑)
마우스로 드래그하면 적용이 되니까....(흑흑)

수정된 코드이다.

$(function(){

  var $linkBtnInput = $('.domain-link-btn-wrap').find('.link-input');

  // 링크 이벤트를 기본으로 선언...
  var linkEvent = 'input focus focusout';

  // 브라우저 property를 사용해서 버전을 return받고
  var isIE = function(){
    var myNav = navigator.userAgent.toLowerCase();
    return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
  };
  
  // 비교하여 ie8이면 이벤트를 재 선언한다..
  if (isIE () == 8) linkEvent = 'input keyup focus focusout';

  // 아래는 위와 같다. 
  $linkBtnInput.on(linkEvent, function(){
  	bytesValidationChk($(this),12);
  });

  function bytesValidationChk(target,maxByte){
    var returnVal = '';
    var currentLength = 0;
    var codeByte = 0;
    var targetVal = target.val();
    
    for (var i = 0; i < targetVal.length; i++) {
      var oneChar = escape(targetVal.charAt(i));
      
      if(oneChar.length > 4) {
          codeByte += 2;
      }else{
          codeByte++;
      }

      if(codeByte <= maxByte){
          currentLength = i + 1;
      }
    }
    
    if(codeByte >= maxByte){
      returnVal = targetVal.substr(0,currentLength);
      target.val(returnVal);
    }
  }
  
});

더 좋은 방법을 알았으면 좋겠다 (헝헝 ㅠㅠ)

+ Recent posts