JavaScript/CSS

Canvas fingerprinting - 쿠키 없이 사용자 추적

페이지 정보

profile_image
작성자 최고관리자 작성일 17-02-27 16:27 조회 427 댓글 0

본문

  • Canvas fingerprinting(canvas 지문 채취)는 브라우저 쿠키 없이 웹사이트에 접속한 사용자를 uniquely 하게 식별하여 추적하는 브라우저 fingerprint 기술 중 하나. (식별 정확도가 100%가 아니기 때문에, 광고 타겟팅에만 주로 사용.)
  • 사용중인 곳: 미국 백악관 사이트 를 포함하여 상위 1만개의 사이트중 5.5% 이상이 사용하고 있다.
  • 쿠키보다 무서운 점은.
    • 사용자가 내가 추적되고 있는지를 알 수 없고
    • 사용자가 추적을 거부할 수 없다

구현

Canvas Fingerprinting

  • 사용자가 방문하면
  • 브라우저는 HTML5 canvas element를 사용하여 이미지를 그리게 한다.

아래 코드와 같이 fillStylefillTextfillRect 와 같은 canvas API 로 이미지를 만든다.

var txt = "BrowserLeaks,com 1.0";
ctx.textBaseline = "top";
ctx.font = "14px 'Arial'";
ctx.textBaseline = "alphabetic";
ctx.fillStyle = "#f60";
ctx.fillRect(125,1,62,20);
ctx.fillStyle = "#069";
ctx.fillText(txt, 2, 15);
ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
ctx.fillText(txt, 4, 17);
  • 렌더링 되는 이미지는 PC마다 미묘하게 달라서, 고유 이미지가 된다.
    • 미묘한 차이가 어디에서 오지?
      • PC에 설치된 GPU 또는 그래픽 드라이버의 차이
  • 만들어진 이미지를 canvas.toDataURL.replace("data:image/png;base64,",""); 와 같이 인코딩하여 서버로 보낸다.
  • 서버는 받은 이미지에 번호를 매기고(실제로는 해싱을 하겠지), 타겟팅 광고 등을 한다.

p.s,

  • DSP는 쿠키를 써서 여러 매체에 리타겟팅 광고를 하는데.
  • 사파리는 외부 쿠키를 금지하고 있고, 다른 브라우저도 미래에 금지할 수 있다. (요즘 분위기를 보면 그럴 가능성이 높아보인다.)
  • 쿠키가 막히면 리타겟팅을 할 수 없다.
  • 그래서 쿠키 없이 사용자를 식별하려는 시도가 많다.
  • 그 시도 중 가장 정확도가 높은 것이 Canvas Fingerprint 인 듯.

댓글목록

등록된 댓글이 없습니다.

게시물 검색
전체 39건 1 페이지
  • selenium + nodeJS
    WebDriver의 객체관계도top이번에는 스크린샷 기능만 배우지만 우선 이쯤에서 WebDriver와 그 관련된 클래스구조를 살펴보는 시간을 갖겠습니다. 우선 전체적인 구조는 다음과 같습니다.WebDriver의 manage, navigate, switchTo는 가각 관련된 인스턴스를 생성해 반환하게 됩니다.이 서브객체들은 저마다의 역할을 수행하는데 Options나 TargetLocater는 거기서 다시 서브객체를 만들게 됩니다.사정이 이렇다보니 하고 싶은 일이 있으면 driver.manage().window().setPosition(10,10) 이런 식으로 길게 체이닝이 되는 경우가 있는데 이 경우도options = driver.manage() 이고window = options.window() 로 다시 서브객체가 나오고 최종적으로window.setPosition(10, 10) 을 호출한 셈입니다.3개로 시작된 driver의 메소드에서 꼬리에 꼬리를 물어 총 6개의 클래스와 연결 짓게 됩니다.Logs – 브라우저 로그를 가져옮Timeouts – 타임아웃과 관련된 정책을 세움Window – 브라우저를 통제함Navigation – 브라우저 네비게이션을 통제함TargetLocator – 현재 문서와 관련된 다른 창을 연결함Alert – 다이얼로그창을 제어함이제 객체 관계도에 따라 각 클래스에 기술된 메소드 전체 목록을 적어봤습니다.driver.manage() – Options객체를 반환합니다. Options객체는 아래와 같은 메소드를 제공합니다.addCookie({name,value,domain,path,expiry,secure,httpOnly}) – 쿠키를 추가합니다.deleteAllCookies() – 모든 쿠키를 삭제합니다.deleteCookie(name) – 특정 쿠키를 삭제합니다.getCookies() – then의 v로 쿠키배열을 반환하는데 각 배열요소는 {name,value,domain,path,expiry}형태의 오브젝트입니다.getCookie(name) – 특정 쿠키를 얻어옵니다. 위와 같고 단일오브젝트를 반환합니다.logs() – Logs객체를 반환합니다. 이 객체는 브라우저에서 console.log 등에 쓴 값을 가져옵니다.get(type) – 해당 type에 대한 로그를 가져옵니다. 한 번 가져오면 그 뒤로는 새것만 가져옵니다.getAvailableLogTypes() – 해당 브라우저가 지원하는 로그 타입을 배열로 반환합니다.timeouts() – Timeouts 객체를 반환합니다. 묵시적 대기를 설명할때 등장한 적이 있습니다. 메소드는 다음과 같습니다.implicitlyWait(ms) – 묵지적 대기를 설정합니다.setScriptTimeout(ms) – 브라우저 내의 스크립트 타입아웃값을 조정할 수 있습니다. 0이하가 되면 타임아웃이 없어집니다.pageLoadTimeout(ms) – 페이지로딩을 위해 대기할 시간을 정할 수 있습니다.window() – Window객체를 반환합니다. 현재 브라우저 그 자체입니다.getPosition() – 브라우저의 윈도우상 위치를 {x, y} 로 반환합니다.setPosition(x, y) – 브라우저의 위치를 옮깁니다.getSize() – 브라우저 크기를 {width, height}로 얻습니다.setSize(width, height) – 브라우저의 크기를 조정합니다.maximize() – 브라우저를 최대화합니다.driver.navigate() – Navigation객체를 반환합니다. 이 객체는 back(), forward()와 같이 브라우저에서 버튼 네비게이션이 하는 일을 시킬 수 있습니다.to(url) – 특정 url로 이동시킵니다.back() – 뒤로가기forward() – 앞으로 가기refresh() – 리로딩driver.switchTo() – 브라우저 내에서 제어권을 옯겨주는 TargetLocator객체를 반환합니다. 이를 통해 다이얼로그, 아이프레임, 팝업창 등으로 이동해다니면서 작업할 수 있습니다.activeElement() – 해당 창의 루트(doc 또는 doc.body 또는 doc.documentElement)웹엘리먼트를 반환합니다.defaultContent() – 원래 driver가 가리키던 창으로 제어를 되돌립니다.frame(id)- 지정한 프레임으로 제어권을 옮깁니다.window(nameOrHandle) – 지정한 윈도우로 제어권을 옮깁니다. 이때 이름은 팝업을 띄울 때 윈도우의 이름으로 지정한 값입니다.alert() – alert, confirm, prompt 등의 다이얼로그로 제어권을 옮깁니다. Alert객체를 반환합니다.getText() – 다이얼로그의 텍스트값을 읽습니다.authenticateAs(username, password) – 기본인증 등 인증창인 경우 아이디, 비번을 입력합니다.accept() – 확인버튼을 누릅니다.dismiss() – 취소버튼을 누릅니다.sendKeys(text) – prompt 등에 텍스트값을 타이핑해줍니다.…
    작성자최고관리자 시간 07-16 조회 179
  • 다른 버전의 jQuery와 충돌
    흔한 경우는 아니지만 여러 버전의 jQuery를 사용하는 경우가 있습니다. 이런 경우 충돌을 방지하는 방법은 버전별로 alias를 따로 만들어 주는 것입니다.<script src='jquery-1.11.1.js'></script>
    <script>
    var jb = jQuery.noConflict();
    </script>
    <script src='jquery-2.1.1.js'></script>
    <script>
    var hs = jQuery.noConflict();
    </script>1.11.1을 사용할 때는 jb를, 2.1.1을 사용할 때는 hs를 alias로 사용합니다.…
    작성자최고관리자 시간 05-14 조회 177
  • 웹에서 SVG 사용하기 실습 가이드
    우리는 픽셀의 시대를 살아가고 있습니다. 웹 디자이너와 웹 개발자들에게 픽셀이란 뗄레야 뗄 수 없는 친구이면서 골치덩어리입니다. 완벽한 웹 사이트를 위해서는 파일 용량을 줄여 성능을 높여야 합니다. 웹 상에 아이콘, 로고, 일러스트레이션 이미지 등을 사용한다면, SVG를 사용하는 것이 유일한 방법입니다. SVG는 확장 가능한 벡터 그래픽(Scalable Vector Graphics)의 약자로 모든 스크린에서 화질이 선명하며, 최소 용량이고, 편집과 수정이 쉽다는 장점을 지니고 있기 때문입니다.

     본 실습 가이드에서는 웹에서 SVG 사용법에 관한 유용한 팁과 방법들을 알려드리고, 여러분의 웹 사이트 개발 과정에 최대한 활용하실 수 있게 도움을 드리고자 합니다.…
    작성자최고관리자 시간 04-02 조회 200
  • 이더리움 dApp 개발을 공부하기
    이더리움 dApp 개발을 공부하기 …
    작성자최고관리자 시간 03-23 조회 300
  • 매크로 생활코딩
    매크로란?Macro. 사용자의 동작을 기록해서 나중에 재사용 할 수 있도록 하는 방법으로 반복되는 작업을 줄여준다.매크로 사용법메뉴 Tools > Record Macro 를 선택한다. 메뉴 Tools > Stop Recording Macro를 선택하기 전까지 사용자의 행동이 기록된다. 저장된 매크로를 실행하려면 메뉴 Tools > Playback Macro 를 선택한다. 방금 만든 매크로를 이후에도 사용하려면 메뉴 Tools > Save Macro 를 선택하고 파일로 저장한다. …
    작성자최고관리자 시간 02-12 조회 340
  • 오토핫키 기초강좌 -킴영감이야기
     전체 강좌 1강 - 오토핫키(AutoHotKey) 소개 2강 - 프로그래밍의 시작, GUI 만들기 3강 - 매크로 프로그래밍 1 (Button, Loop, if 사용법) 4강 - 매크로 프로그래밍 2 (ImageSearch, Send, Sleep) 5강 - 매크로 프로그래밍 3 (Gui Submit) 6강 - 매크로 만들기 응용 1 (if 응용, CoordMode) 7강 - 매크로 만들기 응용 2 (핫키, if 응용) 8강 - 매크로 만들기 응용 3 (While, GUI와 변수의 활용 1) 9강 - 매크로 만들기 응용 4 (GUI와 변수의 활용 2) 10강 - 매크로 만들기 응용 5 (함수1) 11강 - 매크로 만들기 응용 6 (함수2) 12강 - 매크로 제작 예제 …
    작성자최고관리자 시간 02-12 조회 769
  • Felix의 Node.js 가이드
    Node.js 초보 가이드node.js를 처음 사용하는 경우이 가이드는 hello world에서 첫 번째 앱을 배포하는 데 사용됩니다.Node.js 스타일 가이드일반적인 JavaScript 스타일로 node.js와 함께 사용하는 것이 좋습니다. 이 중 많은 부분이 개인적인 취향이지만 잘하면 일관된 것입니다.Node.js 커뮤니티 가이드node.js 커뮤니티에 대해 알아보고 어디서 놀 수 있는지 알아보십시오.Node.js Boss 가이드 설득node.js가 어디에서 의미가 있는지 알아보고 관리를 통해 이점을 확인하는 방법을 알아보십시오.더 많은 가이드가 작동 중입니다. GitHub 저장소 를 따르 거나 차후 가이드의 목록을 살펴보십시오.…
    작성자최고관리자 시간 11-08 조회 171
  • Casper.js를 이용하여 웹사이트 데이터가져오기
    서론국내 최초 자바스크립트 컨퍼런스(http://jscon.ebrainus.com)에 다녀와서 흥미로운 주제를 많이 접할 수 있었는데 그중에 하나가 바로 Casper.js였다. 이번 자바스크립트 컨퍼런스에 대한 내용은 따로 포스팅하기로 하고 일단 연구원답게 잊어버리기 전에 기술부터 연구해보기 했다. 일전에 블로그에 웹 스크래핑하는 방법을 포스팅한 적이 있다. 그 때는 Node.js를 이용해서 웹 데이터를 가져오는 주제로 포스팅을 했는데 PhantomJS를 사용하는 내용을 포함하고 있다. CasperJS는 이 PhantomJS를 포함하고 있다. 예전부터 웹의 네비게이션을 자동화하여 필요한 데이터를 추출하고 싶었는데 좀더 인공지능적으로 사람처럼 행동하는 프로그래밍을 하기 위해서 복잡한 코드를 사용해야만 했다. 즉, 로그인을 한 뒤 어떤 정보를 가져오는 것 처럼 사람의 행동을 뭔가 컴퓨터가 자동적으로 해줘서 필요한 데이터를 수집해주기 위해서는 생각보다 복잡한 코드가 많이 필요하다. CasperJS는 사람이 브라우저를 열어서 뭔가 행동을 하는 것을 동일하게 해낼 수 있다. 실제 CasperJS는 Web Browser engine을 가지고 있다. 이 말은 사람이 브라우저를 열어서 웹 Documents를 해석해서 이벤트를 주는 것과 동일하게 할 수 있다는 것을 의미한다. 이제부터 사람이 브라우저로 하는 행동을 CasperJS로 처리하기 위해서 어떻게 해야하는지 살펴보자.CasperJS 설치먼저 CasperJS를 설치한다. CasperJS는 PhantomJS와 Python을 요구하고 있다. PhantomJS로 마찬가지로 node module로 설치하는 방법이 있고 일반 설치파일을 설치하는 방법이 있다. 후자는 Homebrew를 사용하면 간단하게 설치할 수 있다. 우리는 Node.js의 모듈로 설치해보자.npm install -g casperjs
    CasperJS를 이용해서 Web Scraping 하기앞에서 포스팅한 웹에서 데이터 가져오기 테스트를 Casper를 이용해서 계속 진행해보자. 앞의 예제는 다음 글을 먼저 살펴보기 바란다.(http://blog.saltfactory.net/224) 간단히 설명하면 브라우저가 아닌 프로그램을 사용해서 웹 사이트의 특정 Element의 값을 가져오는 것인데, PhantomJS는 브라우저는 아니지만 실제 브라우저 엔진을 가지고 있어서 브라우저를 열어서 HTML DOM object를 접근하는 것과 동일하게 할 수 있다는 것이다. CasperJS도 이와 비슷하다. CasperJS는 다음과 같이 구현할 수 있다. 브라우저 안에서 HTML 문서를 접근하기 위해서 document를 이용해서 접근하는것과 마찬가지로 CasperJS에서도 document 객체에서 동일하게 접근이 가능한데 CasperJS가 브라우저 엔진을 사용하고 있기 때문이다.// filename : app.js
    // author : saltfactory@gmail.com

    var casper = require('casper').create();

    function getTodayCount(){
    return document.querySelector('#side_today_count').innerText;
    }


    casper.start('http://blog.saltfactory.net', function(){
    var side_today_count = this.evaluate(getTodayCount);
    console.log("오늘의 방문자 수 : " + side_today_count);
    })


    casper.run();
    위 코드를 실행해보자. 실행은 casperjs로 실행을 한다.casperjs app.js
    CasperJS를 사용하는 것이 왠지 PhantomJS를 사용하거나 Node.js의 라이브러리를 사용해서 웹 데이터를 스크래핑하는 것보다 훨씬 간단한거 같다. 마치 웹 브라우저안에 DOM 접근을 직접하는 느낌마저 든다. casperjs 라는 명령어 대신에 casperjs를 Node.js 어플리케이션의 라이브러리로 사용하기 위해서는 SpookyJS라는 CasperJS 드라이버를 사용해야한다. CasperJS를 좀 더 살펴보기로 하자.CasperJS를 이용해서 웹 사이트 네비게이션하기CasperJS의 가장 흥미로운 것이 바로 사람이 브라우저의 행동을 순차적으로 Casper가 그대로 할 수 있다는 것이다. 오늘 방문자 수를 확인하기 위해서 브라우저를 여는게 복잡하고 귀찮아서 웹 스크래핑을 이용해서 간단하게 방문자수를 확인했다. 티스토리가 훌륭한 블로그이지만 네이버 블로그처럼 댓글이 달리면 알람을 주는 기능은 없다. 그래서 티스토리 블로그의 관리자 페이지에서 댓글을 확인하는데 이것 또한 매번 댓글을 확인하기 어렵기 때문에 CasperJS로 이것을 해보려고 한다. 티스토리 블로그의 관지자 주소는 다음과 같다. http://blog.saltfactory.net/admin/center/ 이 주소를 브라우저에서 열면 다음과 같이 관리자 로그인 페이지로 넘어가게 된다.그리고 티스토리 로그인 정보를 입력하면 다시 관리자 페이지로 이동하게 된다. 우리는 CasperJS로 이 작업을 해보려고 한다.CasperJS로 첫번째 URL 요청하기먼저 티스토리블로그 관리자센터에 CasperJS로 접근한다. CasperJS의 진행사항을 살펴보기 위해서 create 할 때 options을 추가한다.// filename : app.js
    // author : saltfactory@gmail.com

    var casper = require('casper').create({verbose: true, logLevel: "debug"});

    casper.start('http://blog.saltfactory.net/admin/center/');
    casper.run();
    CasperJS의 실행 결과를 살펴보면 처음에 http://blog.saltfactory.net/admin/center/를 요청했지만 나중에 내부적인 세션체크가 이루어지고 난 다음에 자체적으로 http://saltfactory.tistory.com/login?requestURI=http://blog.saltfactory.net/admin/center/&try=1 로 URL이 변경된 것을 확인할 수 있다. 이제 변경된 URL이 열린 페이지, 즉, 로그인 페이지에서 form에 아이디와 비밀번호를 넣어서 로그인체크를 하고 우리가 처음에 요청한 http://blog.saltfactory.net/admin/center로 돌아다는 일을 해야한다.CasperJS로 웹사이트 로그인 Form 입력해서 submit 하기CasperJS에서는 form을 채워서 submit을 해주는 메소드가 존재한다. 바로 casper.fill() 메소드이다. 이때 fill()에 들어가는 것은 form을 선택하고 그 form 안에 input을 넣어주면 된다. 위의 로그인 페이지 소스를 분석하면 form은 id로 LoginForm 으로 만들어져 있고, input은 loginid를 입력 받는 nam이 loginid와 password를 입력받는 name이 password로 구성되어져 있는 것을 확인할 수 있다.위 과정을 CasperJS 소스코드로 다음과 같이 구현할 수 있다. CapserJS는 순차적으로 사람의 행동과 동일하게 진행시킬 수 있는 데 then을 사용하면 앞의 행위 다음의 행위를 지정할 수 있다. 이것에 대한 내용은 다음에 좀더 깊게 자세히 하도록 하겠다. 여긴선 단순히 then으로 앞의 일을 그대로 받아와서 처리할 수 있다고만 생각하자.// filename : app.js
    // author : saltfactory@gmail.com

    var casper = require('casper').create({verbose: true, logLevel: "debug"});

    casper.start('http://blog.saltfactory.net/admin/center/');

    casper.then(function(){
    this.fill('form#LoginForm', {
    'loginid':'아이디',
    'password':'비밀번호'
    }, true);
    });

    casper.run();
    실행한 결과는 다음과 같다. 살펴보면 form element를 selector를 이용해서 찾아서 loginid 필드에 값을 set하고 password 피드에 값을 set하고 HTTP Post로 submit을 진행한다. 그리고 로그인체크가 끝나면 우리가 세션이 필요한 요청한 페이지로 다시 URL을 변경시켜 돌아가게 해준다.CasperJS를 이용해서 필요한 데이터 가져오기로그인이 완료된 상태로 우리가 요청한 http://blog.satlfactory.net/admin/center 페이지로 갔을 때 우리는 최근 댓글을 가져오고 싶다. 그래서 페이지를 분석하면 다음과 같다. 다음과 같이 최신댓글은 div 태그에 id가 recentComments로 만들어져 있고 각각 댓글은 span의 class가 txt로 이루어져 있다.그래서 최근댓글 중에서 가장 첫번째 댓글을 가져오기 위해서 다음과 같이 querySelector와 querySelectorAll을 사용해서 필요한 데이터에 접근할 수 있다. 아래 코드를 실행하면 티스토리 관리자 페이지에서 최근 댓글중에 첫번째 댓글을 가져오는 것을 확인할 수 있다.// filename : app.js
    // author : saltfactory@gmail.com

    var casper = require('casper').create({verbose: true, logLevel: "debug"});

    casper.start('http://blog.saltfactory.net/admin/center/');

    casper.then(function(){
    this.fill('form#LoginForm', {
    'loginid':'아이디',
    'password':'비밀번호'
    }, true);
    });

    casper.then(function(){
    var latestComment = function(){
    return document.querySelector("#recentComments").querySelectorAll('span.txt')[0].innerText;
    };

    console.log("최신 댓글 : " + this.evaluate(latestComment));
    });

    casper.run();
    결론CasperJS는 사람이 웹사이트에서 사이트를 브라우징하는 것과 같은 일을 해낼 수 있다. 국내에서 CasperJS를 이용해서 웹 사이트 스크린샷을 찍는 예제를 찾아볼 수 있는데 이것은 CasperJS가 실제 브라우저 엔진을 가지고 브라우징을 하고 있기 때문이다. 자바 컨퍼런스에 갔을 때도 CasperJS를 가지고 사이트에 로그인해서 화면 캡처를 찍는 예제를 보여줬는데, CasperJS가 스크린샷을 만들어낼 수 있는 것은 그리 중요하지 않다고 생각하고 CasperJS가 사람의 행동을 그대로 순차적으로 진행해서 사람이 웹 사이트를 브라우징을 하는 것 처럼 할 수 있다는 것은 정말 놀라운 것이였다. 이 포스팅에서도 예제로는 form의 input에 값을 넣고 submit을 하는 예제를 보여줬지만, 실제로 사람이 링크를 클릭하듯, CasperJS가 링크로 누르고 웹 사이트를 이동하고 다닐 수 있다. 또한 개발자가 웹 브라우저에서 JavaScript 파일을 injection하여 테스트를 하는 것 처럼 현재 열려진 사이트에서 CasperJS를 이용해서 JavaScript를 넣고 테스트도 할 수 있다. CasperJS는 이렇게 사람의 행동을 대신하여 자동화 할 수 있는 강력한 기능을 지녔다. 편리한 기술은 항상 양날의 검과 같다. 어떤 사람은 웹 데이터 스크래핑이 법적으로 문제가 된다는 말도 있고, 또한 이런 자동화 기술은 해킹 도구로 사용이 가능하다고 생각한다. 물론 기술을 나쁜 곳에 사용하면 안된다. 우리는 연구원이고 기술적으로 사람의 편리함을 제공해주는 것을 계속적으로 연구하는 일을 하고 있다. 이 과정속에서 보안상 문제가 되는 부분을 찾아서 보안할 수 있을 것이고 그 과정에서 또한 새로운 기술이 창조되고 계속적으로 발전할 것이라고 믿고 있다. 티스토리는 자동 로그인 방지를 막기 위해서 CAPCHA[http://ko.wikipedia.org/wiki/CAPTCHA]가 추가되면 좋을 것 같다.참고http://casperjs.orghttp://nodeqa.com/nodejs_ref/73http://nodeqa.com/nodejs_ref/86…
    작성자최고관리자 시간 07-05 조회 589
  • 홈 / HTML5란? / 표준문서
    홈 / HTML5란? / 표준문서  https://www.koreahtml5.kr/jsp/infoSquare/infoStandardDoc.jsp …
    작성자최고관리자 시간 04-12 조회 193
  • Fingerprintjs - 예제 소스
    MIT에서 만든 Fingerprint  javascript 소스FingerprintjsFinger in tjs한계: 브라우저 기준이다. 브라우저가 업데이트 되거나 같은 기기에서도 다른 브라우저면 다른 것으로 구분된다.…
    작성자최고관리자 시간 02-27 조회 283 댓글 1
  • 열람중
    Canvas fingerprinting - 쿠키 없이 사용자 추적
    Canvas fingerprinting(canvas 지문 채취)는 브라우저 쿠키 없이 웹사이트에 접속한 사용자를 uniquely 하게 식별하여 추적하는 브라우저 fingerprint 기술 중 하나. (식별 정확도가 100%가 아니기 때문에, 광고 타겟팅에만 주로 사용.)University of California, San Diego 의 연구원이 2012년 5월에 쓴 논문 “Pixel Perfect: Fingerprinting Canvas in HTML5” 이 최초.Princeton 대학과 KU Leuven 대학의 2014-07-24 연구 결과로 화제가 되었음. “The Web never forgets: Persistent tracking mechanisms in the wild”사용중인 곳: 미국 백악관 사이트 를 포함하여 상위 1만개의 사이트중 5.5% 이상이 사용하고 있다.Rap Genius, CBS, YouPorn 등사용중인 사이트를 정리한 사이트사용하는 곳 중 95%가 AddThis가 만든 Canvas Fingerprinting 스크립트를 사용.쿠키보다 무서운 점은.사용자가 내가 추적되고 있는지를 알 수 없고사용자가 추적을 거부할 수 없다구현사용자가 방문하면브라우저는 HTML5 canvas element를 사용하여 이미지를 그리게 한다.아래 코드와 같이 fillStyle, fillText, fillRect 와 같은 canvas API 로 이미지를 만든다.var txt = "BrowserLeaks,com 1.0";
    ctx.textBaseline = "top";
    ctx.font = "14px 'Arial'";
    ctx.textBaseline = "alphabetic";
    ctx.fillStyle = "#f60";
    ctx.fillRect(125,1,62,20);
    ctx.fillStyle = "#069";
    ctx.fillText(txt, 2, 15);
    ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
    ctx.fillText(txt, 4, 17);
    렌더링 되는 이미지는 PC마다 미묘하게 달라서, 고유 이미지가 된다.미묘한 차이가 어디에서 오지?PC에 설치된 GPU 또는 그래픽 드라이버의 차이만들어진 이미지를 canvas.toDataURL.replace("data:image/png;base64,",""); 와 같이 인코딩하여 서버로 보낸다.서버는 받은 이미지에 번호를 매기고(실제로는 해싱을 하겠지), 타겟팅 광고 등을 한다.p.s,DSP는 쿠키를 써서 여러 매체에 리타겟팅 광고를 하는데.사파리는 외부 쿠키를 금지하고 있고, 다른 브라우저도 미래에 금지할 수 있다. (요즘 분위기를 보면 그럴 가능성이 높아보인다.)쿠키가 막히면 리타겟팅을 할 수 없다.그래서 쿠키 없이 사용자를 식별하려는 시도가 많다.그 시도 중 가장 정확도가 높은 것이 Canvas Fingerprint 인 듯.…
    작성자최고관리자 시간 02-27 조회 428
  • 실시간 멀티채팅 구현하기!
     웹에서 실시간처리학부생활중 실시간처리 관련으로 TCP/IP를 배우면서 TCP/IP를 이용한 1:1 채팅을 구현해보셨을것이라 생각합니다. 하지만 실무에서는 전~~~~혀 쓸모가 없는 것 같습니다;; 수업중 책에 나와있는 소스대로 따라한다면 1:1채팅은 잘 되지만 멀티채팅구현은 머리를 굴리고 굴려야 간신히 구현할 수 있을 겁니다. 그러나 역시 실제서비스에 적용은 무리라고 생각됩니다.그럼, 쉽게 프로그래밍을 짜면서 실제서비스에서 적용할 수 있는 방법이 무엇이 있을까요?멀티채팅관련으로 알아보면서 괜찮은 것을 하나 찾았습니다 : )요즘 젊은층(?)에서 많이 사용하고 있는 node.js + socket.io 입니다. 이걸 언어라고 설명을 해야할지 프레임워크라고 설명을 해야할지 애매합니다. node.js자체가 javascript를 기반으로 만들어진것으로 알고있습니다.Wiki(node.js위키링크)를 참고하면 Node.js는 확장성 있는 네트워크 어플리케이션(특히 Server-side) 개발에 사용되는 소프트웨어 플랫폼이라고 정의되어 있습니다.음. 저는 일단 프레임워크로 구분하겠습니다. 서버프로그램구현에 있어서 javascript언어를 이용하면서 특화되었다고 생각하시면 될 것 같습니다.저는 javascript언어가 그렇게 익숙치않아서 가끔씩 문법을 확인하면서 작성하는데 언어가 익숙하신 분들은 정말 쉽게 작성하면서 놀랠 것 같네요. 후후node.js + socket.ionode.js + socket.io? 이게 무엇일가요?일단 node.js는 서버프로그램이라는 것은 알겠지만 socket.io 확장자부터 참 이상합니다. 간단하게 설명드리면 소켓통신을 쉽게 구현할 수 있도록 도와주는 아이라고 말씀드릴 수 있습니다.node.js와 socket.io가 만나면 아까 위에서 힘들게 구현하던 멀티채팅을 순식간에 짧고 굵게 구현할 수 있습니다!성능이 의심스러우신가요? 저는 테스트해보지 않았지만 다른분들께서 테스트한 내용들을 보게되면 실.시.간 접속 몇천명까지는 무리없이 처리해준다고 합니다! 엄청큰 서비스를 하지않는다면 몇천명이 정확하게 동시에 접속할일이 많을까요? 제 개인적으로는 그런걱정을 하고있다면, 그 서비스는 이미 성공했기 때문에 능력있는 개발자를 자신있게 영입하면 됩니다 :D 하하하하하하이렇게 말만 주저리주저리해봤자 머리만 더 복잡해질 것 같네요. 직접 실습을 통해서 얼마나 위대한지 같이 확인해도록 합시다 : )채팅 Servernode.js - node.js 링크socket.io - Socket.IO 링크본격적인 적용을 위해 위에 있는 두 웹사이트를 들어가서 설치를 해주세요. node.js를 설치하신 뒤 socket.io를 준비해주시면 됩니다 : )기본적인 SOCKET통신을 활용하는 방법이 socket.io 웹사이트에 설명되어 있네요./* Server Source */
    var io = require('socket.io').listen(80);

    io.sockets.on('connection', function (socket) {
    socket.emit('news', { hello: 'world' });
    socket.on('my other event', function (data) {
    console.log(data);
    });
    });
    /* Client Source */
    <script src="/socket.io/socket.io.js"></script>
    <script>
    var socket = io.connect('http://localhost');
    socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
    });
    </script>
    이렇게 서버쪽과 클라이언트에 위 예제소스를 적용하시면 실시간으로 통신할 수 있는 페이지가 완성됩니다 : ) 하지만 “위에 있는 소스가지고 채팅을 어떻게 만들어?” 하시는 분이 있을지도 모르겠습니다./* 실제 적용한 Server Source */
    var io = require('socket.io').listen(50000);

    io.sockets.on('connection', function(socket) {
    socket.emit('connection', {
    type : 'connected'
    });

    socket.on('connection', function(data) {
    if(data.type == 'join') {

    socket.join(data.room);

    socket.set('room', data.room);

    socket.emit('system', {
    message : '채팅방에 오신 것을 환영합니다.'
    });

    socket.broadcast.to(data.room).emit('system', {
    message : data.name + '님이 접속하셨습니다.'
    });
    }
    });

    socket.on('user', function(data) {
    socket.get('room', function(error, room) {
    socket.broadcast.to(room).emit('message', data);
    });
    });

    });
    위에는 제가 이것저것 수집하면서 제대로 작동하도록 만들어본 서버소스입니다 : )각 사용자들이 원하는 채팅방에 접속하여 서로 실시간으로 채팅할 수 있도록 지원해주는 서버입니다.socket.io에 의해서 사용자가 해당방에 접속하여 글작성시 서버는 같은방에 있는 타접속자에게 해당메세지를 브로드캐스트해주는 역할을 합니다.만약 대화한 내용들을 저장하고 싶다면 데이터가 넘어오는 시점에서 원하는 DB에 Connection하여 기록하면 됩니다 : ) 저는 여기서 요즘 유행한다는 MongoDB(몽고DB)를 이용해보았고, 실험결과! 만족스러웠습니다.그럼 다음은 Client에서는 어떻게 같은 방에 접속하며, 메세지를 주고받을 수 있는지 살펴보도록 하겠습니다!채팅 Client바로 위에서 아주아주아주 간단하게 Client소스를 보셨지만, 감이 잘 안오실 것 같네요. 그래서 나름 샘플소스를 준비해보았습니다. 아주 기본적으로 대화할 수 있도록 만들어보았습니다 : )참고하셔서 클라이언트와 서버 모두 직접 구현해보아요 : )<!DOCTYPE html>
    <html>
    <head>
    <style>
    .footer {
    width: 100%;
    height: 50px;
    position: fixed;
    bottom: 0;
    }
    </style>
    </head>
    <body>
    <div class='j-message'>
    </div>
    <div class='j-footer'>
    <table>
    <tr>
    <td width='100%'>
    <input id='message-input' type='text'>
    </td>
    <td width='20%'>
    <button id='message-button' type='submit'> 전송 </button>
    </td>
    </tr>
    </table>
    </div>

    <script type="text/javascript" src="http://chat.socket.io/socket.io/socket.io.js"></script>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>

    <script>
    var serverURL = 'localhost:50000';

    var name = 'jin';
    var room = '100';

    $(document).ready(function() {
    var socket = io.connect(serverURL);

    socket.on('connection', function(data) {
    if(data.type == 'connected') {
    socket.emit('connection', {
    type : 'join',
    name : name,
    room : 100
    });
    }
    });

    socket.on('system', function(data) {
    writeMessage('system', 'system', data.message);
    });

    socket.on('message', function(data) {
    writeMessage('other', data.name, data.message);
    });

    $('#message-button').click(function() {
    var msg = $('#message-input').val();

    socket.emit('user', {
    name : name,
    message : msg
    });

    writeMessage('me', name, msg);
    });

    function writeMessage(type, name, message) {
    var html = '<div>{MESSAGE}</div>';

    var printName = '';
    if(type == 'me') {
    printName = name + ' : ';
    }

    html = html.replace('{MESSAGE}', printName + message);

    $(html).appendTo('.j-message');
    }
    });
    </script>
    </body>
    </html>
    음… 졸면서 클라이언트 소스를 작성하기는 했는데, 잘 돌아가는지 테스트는 못해봤네요 ㅠㅠ 참고하시면서 작성하시면 잘될겁니다 : )멀티채팅. 어려울 것 같았지만 저희는 너무나도 좋은 세상에 살고 있습니다.대부분 라이브러리, 프레임워크 형태로 구현되어 있고, 잘 가져다가 사용하면 됩니다. 과거였다면 으~~~ 생각만해도 끔찍합니다.하지만 저희는 이렇게 편리하게 구현되어있는 것들을 가지고 엄청난것을 만들어야 합니다.카카오톡, 라인, 와츠앱을 넘어 더 좋은 채팅을 많이 많이 개발해보아요 : )지금까지 읽어주셔서 감사합니다.위에 기술한 내용은 조만간 잘 정리하여 GitHub에 오픈소스로 공개할 예정입니다.등록하면 이곳에 주소 적어놓겠습니다. 감사합니다. Github에 등록하였습니다 : https://github.com/devjin0617/nodejs-socket.io-chat-example출처: http://blog.puding.kr/156 [Jin] …
    작성자최고관리자 시간 01-18 조회 2453
  • [jquery] datepicker 시작일과 종료일 설정시 사용하기 좋은 팁
        $ (' # sdate').datepicker();
        $ (' # sdate').datepicker("option", "maxDate", $ ("#edate").val());
        $ (' # sdate').datepicker("option", "onClose", function ( selectedDate ) {
            $ ("#edate").datepicker( "option", "minDate", selectedDate );
        });
     
        $ (' # edate').datepicker();
        $ (' # edate').datepicker("option", "minDate", $ ("#sdate").val());
        $ (' # edate').datepicker("option", "onClose", function ( selectedDate ) {
            $ ("#sdate").datepicker( "option", "maxDate", selectedDate );
        });
    작성자최고관리자 시간 05-11 조회 2876
  • [jQuery] datepicker 특정일 선택 안되도록 설정

     


    토요일, 일요일은 선택이 안되도록 또는 특정일자는 선택이 안돼도록 설정할 수 있습니다.

    아래 예제 소스에서 굵은 글자로 표시된 부분을 참조해주세요.

    beforeShowDay 값에 해당 일자의 표시여부를 판단하는 함수를 적어주시면 됩니다.

    각 상황별 함수는 그 아래에 첨부하였습니다.

     

    HTML  파일

    $('#input4').datepicker({
        showOn: 'button',
        buttonImage: '<?=$g4[path]?>/img/calendar.gif',
        buttonImageOnly: true,
        buttonText: "달력",
        changeMonth: true,
        changeYear: true,
        showButtonPanel: true,
        yearRange: 'c-99:c+99',
        minDate: '+1d',
        maxDate: '+100d',
        beforeShowDay: noSundays

    });

     

    상황별 함수

     

    // 특정날짜들 배열 
    var disabledDays = ["2013-7-9","2013-7-24","2013-7-26"];


    // 주말(토, 일요일) 선택 막기 
    function noWeekendsOrHolidays(date) { 
       var noWeekend = jQuery.datepicker.noWeekends(date); 
       return noWeekend[0] ? [true] : noWeekend; 
    }

     

    // 일요일만 선택 막기  
    function noSundays(date) {  
     return [date.getDay() != 0, ''];  


     

    // 이전 날짜들은 선택막기 
    function noBefore(date){ 
       if (date < new Date()) 
           return [false]; 
       return [true]; 
    }

    // 특정일 선택막기 
    function disableAllTheseDays(date) { 
       var m = date.getMonth(), d = date.getDate(), y = date.getFullYear(); 
       for (i = 0; i < disabledDays.length; i++) { 
           if($.inArray(y + '-' +(m+1) + '-' + d,disabledDays) != -1) { 
               return [false]; 
           } 
       } 
       return [true]; 
    }


    작성자최고관리자 시간 05-11 조회 1935
  • Slideshow
    Slideshow샘플 사이트…
    작성자최고관리자 시간 03-27 조회 862

회원로그인

Copyright © 2001-2016 ITNANUM. All Rights Reserved..