개발팁2018. 12. 26. 16:07


윈도우 OS 에서는





일정한 시간 (화면보호기 시간) 이 지나면 화면보호기(또는 바로 잠금화면)가 나타나기도 하고,

윈도우키 + L 키를 누르면, 화면잠금 기능이 바로 동작한다.

모니터상에 표시된 내용을 감추고(배경이미지를 노출하여), 로그인되어 있는 사용자의 비밀번호를 올바르게 입력해야만 잠금이 풀리게 된다.


웹에서는 자바스크립트만으로 이러한 기능을 구현할 수 있다.




구현할 기능은 아래와 같다.


1. 일정시간이 지나면, 잠금화면의 레이어가 현재 화면 위에 뜬다. (레이어 Show)

2. 또는, 특정키를 누르면 ( 여기서는 Ctrl + Alt + D 로 정의할 것이다.) 1번의 잠금상태로 전환된다.

3. 비밀번호를 올바르게 입력하면, 잠금화면이 해제 (레이어가 Hide) 

4. 브라우저의 탭을 이용하여, 같은 브라우저 세션으로 접근하더라도, 잠금 화면은 계속 유지되어야 한다. (잠금해제를 하지 않으면, 사이트를 이용할 수 없다. 또는 재로그인)


레이어 UI 는 아래와 같이 구현하였다. 사용자 개발 환경에 맞게 구현하면 되고, 예제에서는 Bootstrap 를 이용하였다.


DIV 태그는 BODY 태그 아래에 두면 된다. 파셜뷰(닷넷) 로 구현해도 된다.


class="hide" 로 인해, 평상시에는 화면에 노출되지 않다가, 잠금기능이 동작하면 (class='show'), 전체화면을 덮어버리고, 95% 로 opacity 를 채워서 기존 내용을 확인이 어렵게 하고, 로그인한 유저 이름을 표시하고, 비밀번호를 입력받게 된다.


<div id="screen-lock" class="hide" style="opacity:0.95;">

    <div class="panel panel-warning" style="width:500px;margin: 168px 0px 0px -250px;left: 50%;position: absolute;">

        <!-- begin panel-heading -->

        <div class="panel-heading">

            <h4 class="panel-title" data-i18n="message.screenlock_message">screenlock_message</h4>

        </div>

        <!-- end panel-heading -->

        <!-- begin panel-body -->

        <div class="panel-body">

            <!-- begin fieldset -->

            <fieldset>

                <!-- begin row -->

                <div class="row">

                    <!-- begin col-8 -->

                    <div class="col-md-10 offset-md-1">

                        <!-- begin form-group -->

                        <div class="form-group row m-b-10">

                            <label class="col-md-5 col-form-label text-md-right" data-i18n="label.user_name">사용자명</label>

                            <div class="col-md-6">

                                <input class="form-control" readonly value="@ViewBag.user_info.UserName">

                            </div>

                        </div>

                        <!-- end form-group -->

                        <!-- begin form-group -->

                        <div class="form-group row m-b-10">

                            <label class="col-md-5 col-form-label text-md-right" data-i18n="label.password">비밀번호</label>

                            <div class="col-md-6">

                                <input type="password" id="lock_Password" class="form-control" />

                            </div>

                        </div>

                        <!-- end form-group -->

                    </div>

                    <!-- end col-8 -->

                    <div class="icon" style="padding-top: 5px;position: absolute;padding-left: 35px;">

                        <i class="fa fa-unlock fa-5x" style="color:#919191;"></i>

                    </div>

                    <div class="panel-footer" style="width:100%;text-align: center;">

                        <button id="LockPasswordCheckAction" class="btn btn-success" data-i18n="label.unlock">unlock</button>

                        <button class="btn btn-white LogoutAction" data-i18n="common.logout">logout</button>

                    </div>


                </div>

                <!-- end row -->

            </fieldset>

            <!-- end fieldset -->


        </div>

        <!-- end panel-body -->

    </div>

    <!-- end panel -->

</div>




이제 스크립트로 일정시간이 지났을때, 특정키를 눌렀을때, 잠금 화면을 노출할것이다.


screenlock.initLock = function() {


    screenlock.timerHandle = window.setTimeout(function () {

        screenlock.setLock();

    }, 30 * 1000 * 60); // 30분 경과시 잠금처리


 

    // Ctrl + Alt + L 키를 누려면 강제 잠금 모드로 전환한다.

    $("body").keydown(function (event) {

        if (event.ctrlKey && event.altKey && event.keyCode == 76) {

            screenlock.forceLock();

        }

    });


}


// 강제잠금 기능

screenlock.forceLock = function () {

    // 잠금처리

    $.cookie(screenlock.cookieName, 1, { path: '/' });


    $('#screen-lock').removeClass("hide");

    $('#screen-lock').addClass("show");

}




공통으로 호출되는 VIEW화면(html) 에서, (닷넷에서는 레이아웃에서 호출하면된다.)


$(document).ready() 에서 initLock() 를 호출해 주면된다.


일단은, screenlock.setLock 과 screenlock.forceLock 은 똑같이 구현해 준다.


30분이 흐르거나, Ctrl + Alt + L 키를 누르면, 잠금 화면이 나올것이다.


$.cookie(screenlock.cookieName, 1, { path: '/' });


쿠키에 값을 쓰는 이유는,


한번 잠금 상태일경우, 페이지 새로고침이나, 브라우저의 TAB 으로 접근하였을때, 쿠키값을 참고하여, 계속 잠금 상태를 유지하도록 하기 위함이다. (아래에서 구현)



잠금해제는, AJAX 요청으로 서버에서 비밀번호 검증하고 검증이 통과 하였을경우,


아래 코드를 실행해주면된다.


$.removeCookie(screenlock.cookieName, { path: '/' });

window.clearTimeout(screenlock.timerHandle);

// $.removeCookie(screenlock.initCookieName, { path: '/' }); // initCookieName 는 아래에서 다시 설명할 것이다.


$('#screen-lock').removeClass("show");

$('#screen-lock').addClass("hide");



잠금 기능과 해제 기능이 구현이 되었다면, initLock 을 아래와 같이 변경해보자.



screenlock.initLock = function () {

    let isLocked = $.cookie(screenlock.cookieName) != undefined;


     if (isLocked) {

        $('#screen-lock').removeClass("hide")

        $('#screen-lock').addClass("show")

    }

    else {

        screenlock.resetLock();

    }


    // Ctrl + Alt + L 키를 누려면 강제 잠금 모드로 전환한다.

    $("body").keydown(function (event) {

        if (event.ctrlKey && event.altKey && event.keyCode == 76) {

            screenlock.forceLock();

        }

    });


    return isLocked;

}


screenlock.resetLock = function () {

    // timeout 시간을 재설정한다.


    if (screenlock.timerHandle != undefined) {

        window.clearTimeout(screenlock.timerHandle);

    }


    $.cookie(screenlock.initCookieName, (new Date()).getTime(), { path: '/' });


    screenlock.timerHandle = window.setTimeout(function () {

        screenlock.setLock();

    }, 30 * 1000 * 60);

}


여러개의 TAB 을 사용할경우, 하나의 탭에서 잠금상태로 전환되면, (쿠키에 저장하여) 잠금상태를 계속 유지하게 되고,


또한, 여러개의 TAB 에서 1개의 TAB 에서 계속 사용하고 있으면, 나머지 TAB 이 잠기는것을 방지하기 위해,


initCookieName 을 쿠키에 저장할 것이다. 쿠키값은 현재 시간의 timestamp 값이다.


이 값을 사용하여, window.setTimeout 으로 지정된 시간이 지났더라도, 잠기지 않도록 구현할 것이다.


이제, screenlock.setLock 함수를 아래와 같이 다시 재정의 한다.


screenlock.setLock = function () {

    let initTime = $.cookie(screenlock.initCookieName);


    // 쿠키에 저장된 init 날짜를 비교하여, 시간이 경과한경우만, 잠금처리한다.

    // 창을 여러개 띄어놓고 작업할경우, 사용하지 않는 창에서 무조건 락이 걸리는 문제를 해결하기 위해 사용.

    if (initTime != undefined) {

        let curTime = (new Date()).getTime();


        let diff_min = (curTime - parseInt(initTime)) / 1000 / 60 * 1.1; // 10% 오차범위로 처리한다. * 1.1


        //console.log('diff_min', diff_min);


        if (diff_min < screenlock.lockTime) {

            screenlock.resetLock(screenlock.lockTime / 5);  // 1/5 간격으로 다시 검사하도록 한다.


            return;

        }

    }


    // 잠금처리

    screenlock.forceLock();

}



위의 코드는 window.setTimeout 을 사용하여, 30분이 지나면, 잠금기능이 동작하게 되어 있다.



화면이 새로고침 된다면, 이 시간은 다시 셋팅 (resetLock 함수) 이 되기 때문에, 문제가 없는 것처럼 보인다.


하지만 SPA (Single Page Application) 이나, 한 화면안에서 AJAX 요청으로 오래 작업을 하는 경우가 있다면, 사용중에 화면이 잠기는 문제가 있다.


사이트를 사용중일때는 (윈도우 사용이랑 별개) 잠기지 않게 해주어야 한다.


페이지 새로고침없는 상태에서도, 사이트를 사용중이라는 것에 대한 정의가 필요하다.


ex) AJAX 요청이 있다거나, key 를 누른다거나..


key 누르는 이벤트에 대헤서는 아래코드를 initLock 에서 구현할 수 있다.


$("body").keydown(function (event) {

      screenlock.resetLock();

});


이를 이용하여, mouse move 또는 mouse down 이벤트에 대해서도 구현이 가능하다.


두번째는 ajax 요청에 대한 처리이다.

$.ajax 를 이용한다면, $.ajaxSetup 에서 공통 옵션과 콜백함수를 정의할 수 있다. 


$.ajaxSetup({


    beforeSend: function (xhr) {


            if (this.url.indexOf("PasswordCheck") < 0) // 화면잠금에서 비밀번호 체크할때는 제외한다.

                screenLock.resetLock(); // 서버로 AJAX 요청이 올때마다, 화면잠금시간을 연장한다.

    }

});


이제 모든 기능이 구현되었다.



위에서는 잠금상태를 위한 초기 timestamp 값이랑, 잠금상태값을 쿠키에 저장하였지만,

쿠키는 매번 서버로 전송되기 때문에, 불필요한 값이 서버에 전송되기도 한다.


SessionStorage 로 변경도 가능하다.


Posted by 헝개