브라우저 팝업 차단 방지


172

JavaScript에서 순전히 OAuth 인증 흐름을 개발 중이며 팝업에서 사용자에게 "grant access"창을 보여주고 싶지만 차단됩니다.

어떻게에 의해 하나 생성 창 팝업 방지 할 수 있습니다 window.open또는 window.showModalDialog다른 브라우저 '팝업 차단에 의해 차단되는가?


11
가능하더라도 (모름) 사람들이 팝업 차단기를 사용하는 경우이를 존중해야합니다. 대부분의 브라우저는 사이트에서 팝업을 열려고 할 때 메시지를 표시하여 원하는 경우 계속 볼 수 있습니다. 귀하의 사이트에 일부 컨텐츠가 팝업으로 열리고 사용자가 진행하기 위해이를 허용해야한다는 언급을 할 수 있습니다.
Felix Kling

5
가장 좋은 방법은 다음과 같습니다. 1)이 작업을 성공적으로 수행합니다. 2) 화난 웹 고객의 군중이 두려워 두려움에 따라 창문을 닫고 문과 코커를 막습니다. 청중.
Alex Mcp

Alex와 Felix, 질문을 업데이트했습니다. 나는 악에 대한 지식을 사용하지 않을 것이다 :). 감사!
Pablo Fernandez

9
팝업 차단기를 우회하여 실제로 사용자 경험을 향상시키기 위해 노력하고 있다고 덧붙이고 싶습니다. 내가 지금하고있는 예에서, 우리는 Javascript 응용 프로그램 (ExtJS 기반)을 사용하고 있으며 사용자가 paypal을 사용하여 지불하도록 노력하고 있습니다. 새 창에서 페이팔을 시작하기 위해 클릭 할 수있는 버튼을 제공하지만 특정 버전의 IE는 버튼 클릭이지만 팝업으로 차단합니다. 그들이 팝업을 활성화하면 화면이 다시로드되고 JavaScript 앱으로 창 상태가 사라지고 다시 시작해야합니다. 실제로 : 문제는 IE가 바보입니다.
NateDSaint

1
@FelixKling 네 가능합니다. 브라우저 제작자들은 이미 이것에 대해 생각했습니다. 사용자 의도가있는 한 (사용자가 링크 또는 버튼을 클릭하여 신호를 보내면) 팝업을 여는 것이 좋습니다. 팝업 차단기는 사용자 의도를 존중해야합니다. IE의 팝업 차단기가 작동하지 않으면 결함이있는 팝업 차단기입니다. 사용자는 팝업 차단기를 사용하여 스크립트가 팝업을 열지 못하게합니다 (단, 버튼이나 링크를 클릭하여 열려고 시도한 팝업은 차단하지 않음).
Stijn de Witt

답변:


286

일반적인 규칙은 팝업 사용자window.open직접 사용자 조치에 의해 호출되지 않는 자바 스크립트에서 또는 이와 유사한 호출이 발생 하는 경우 팝업 차단기가 참여하는 것 입니다. 즉, window.open팝업 차단기에 치지 않고 버튼 클릭에 대한 응답으로 호출 할 수 있지만 타이머 이벤트에 동일한 코드를 넣으면 차단됩니다. 콜 체인의 깊이 또한 중요한 요소입니다. 일부 구형 브라우저는 즉시 발신자를보고, 최신 브라우저는 발신자의 발신자가 마우스 클릭인지 등을 조금 뒤로 추적 할 수 있습니다. 팝업 차단기를 피하려면 최대한 얕게 유지하십시오.


2
흥미롭게도 선택 요소에 바인딩 된 변경 이벤트를 통해 시작된 팝업은 클릭과 같은 직접 사용자 작업으로 시작하더라도 FF가 아닌 Chrome에서 차단됩니다. 입력에 바인딩되어 있으면 허용됩니다. 이상한.
ccnokes

6
아무도 브라우저가 일관되었다고 말하지 않았습니다. : P
dthorpe

8
실험을 통해 스택 깊이는 팝업 차단기와 관련이 없음을 이해해야합니다. 실제로 사용자 작업 후 1 초 이내에 window.open이 호출되는지 여부를 확인합니다. 크롬 46과 파이어 폭스 (42)에 테스트
Mesqalito

이 페이지의 @ tj-crowder의 답변을 사용하여 무한한 시간을 허용하는 두 브라우저에서 1 초 제한 시간을 피할 수 있습니다 .. ajax를 통해 호출하는 URL이 sleep ( )가 응답을 반환하기 전에 일정 시간 동안 브라우저가 페이지를 '로드'하는 동안 정지합니다. 응답을 받으면 팝업을 트리거합니다. 그러나 Chrome에서는이 트릭이 작동하도록 ajax () 바로 앞에 alert ()을 추가해야합니다.
fanfare

184

를 기반으로 제이슨 세브링매우 유용한 팁을 하고, 물건에 덮여 여기거기 , 내 경우에 대한 완벽한 솔루션을 발견 :

자바 스크립트 스 니펫이 포함 된 의사 코드 :

  1. 사용자 작업에 즉시 빈 팝업을 만듭니다.

    var importantStuff = window.open('', '_blank');

    선택 사항 : "대기 중"정보 메시지를 추가하십시오. 예 :

    a) 외부 HTML 페이지 : 위의 줄을

    var importantStuff = window.open('http://example.com/waiting.html', '_blank');

    b) 텍스트 : 위의 줄 아래에 다음 줄을 추가하십시오.

    importantStuff.document.write('Loading preview...');
  2. 준비가되면 내용으로 채 웁니다 (예 : AJAX 호출이 반환 될 때)

    importantStuff.location.href = 'http://shrib.com';

window.open필요한 추가 옵션으로 전화를 풍부하게하십시오 .

실제로이 솔루션을 mailto 리디렉션에 사용하며 모든 브라우저 (Windows 7, Android)에서 작동합니다. 이 _blank비트는 mailto 리디렉션이 모바일에서 작동하는 데 도움이됩니다.

당신의 경험은? 이것을 향상시킬 수있는 방법이 있습니까?


1
? 브라우저의 사용자 작업이 아닌 경우 어떻게합니까? 예를 들어, 사용자가 서버에 대해 인증 한 후에는 새 탭을 열어야합니다
Don Cheadle

@mmcrae 그렇게하지 마십시오. 무엇을 하려는지 팝업 창보다 더 나은 방법이 있습니다. 그렇지 않으면, 당신의 사이트를보고 싶지 않을 것입니다. 오늘날의 브라우저는 그렇게 할 수 없어야합니다 . @dthorpe의 답변을 참조하십시오 .
스위스 미스터

5
Whatever it is you intend to do, there is a better way than a popup window롤? 홀수 일반화. 고객은 인증 된 페이지가 열린 상태로 유지되고 인증 후 새 사이트 / 방문 페이지가 새 탭에서 열리기를 원합니다. 예, 뛰어난 사용자 경험에 대한 아이디어는 아니지만 합리적으로 보입니다.
Don Cheadle

@mmcrae. 앉아서 진지하게 생각하십시오. 설명하는 시나리오에서 "사용자 작업"을 찾을 것을 약속드립니다. 내 대답의 요점은 사용자 작업이있을 때 팝업 창을 만든 다음 나중에 내용으로 채우는 것입니다. 귀하의 경우 힌트 : 사용자가 "인증"을 누르십시오-> 팝업을 생성하십시오 (빈); timer가 작동했거나 서버 응답이 있거나 무엇이든-> 내용을 팝업으로 채 웁니다.
스위스 미스터

3
유용한 팁, Ajax 요청이 실패하면 전화 importantStuff.close를 걸어 새 탭을 닫고 원래 페이지에서 제공하고 경고하십시오.
Goose

24

또한 스위스 미스터 게시물, 내 경우에는 window.open 이 약속 내에서 시작되어 팝업 차단기가 켜지고 내 솔루션은 다음과 같습니다.

$scope.gotClick = function(){

  var myNewTab = browserService.openNewTab();
  someService.getUrl().then(
    function(res){
        browserService.updateTabLocation(res.url, myNewTab);

    }
  );
};

browserService :

this.openNewTab = function(){
     var newTabWindow = $window.open();
     return newTabWindow;
}

this.updateTabLocation = function(tabLocation, tab) {
     if(!tabLocation){
       tab.close();
     }
     tab.location.href = tabLocation;
}

이것은 약속 응답을 사용하고 팝업 차단기를 호출하지 않고 새 탭을 여는 방법입니다.


1
이것은 나의 해결책으로 이끌었다! 열린 탭이 포함 된 변수를 만든 다음 데이터가로드 된 후 URL을 채 웠습니다. 감사. const tab = window.open(); observable.subscribe(dataUrl => tab.location.href = dataUrl);
jonas

1
팝업 차단기를 활성화하면 팝업 차단기와 관련된 문제가 해결되지 않습니다 ...
Alejandro Vales

@Alejandro Vales jonas 솔루션은 코드가 onClick 이벤트 또는 사용자 상호 작용에서 실행될 경우에만 작동합니다. windows, open promise, timeout, subscribe ...를 통해 새 탭을 열려고하면 브라우저가 사용자의 조작이라고 생각하므로 약속을 입력하기 전에 인스턴스를 만드는 것이 해결책입니다. jonas처럼 href
David

@David 대단히 감사합니다 !!! 나는 .then그때 그때 대답 을 보지 못했고 그것이 내가 너무 혼란스러워하는 이유입니다 : / SRY ...
Alejandro Vales

@David 이것은 훌륭합니다! 매력처럼 작동합니다. 질문 하나만 더해서 귀찮게한다면 Edge에서도이 작업을 수행하는 방법을 알고 있습니까? 권리 자원에 찔러 것 크게 도움이 ...
dzenesiz

21

좋은 습관 으로 팝업이 차단되었는지 테스트하고 경우에 따라 조치를 취하는 것이 좋습니다 . window.open에 반환 값이 있으며 작업이 실패하면 해당 값이 null 일 수 있음을 알아야합니다. 예를 들어 다음 코드에서

function pop(url,w,h) {
    n=window.open(url,'_blank','toolbar=0,location=0,directories=0,status=1,menubar=0,titlebar=0,scrollbars=1,resizable=1,width='+w+',height='+h);
    if(n==null) {
        return true;
    }
    return false;
}

팝업이 차단되면 window.open은 null을 반환합니다. 따라서 함수는 false를 반환합니다.

예를 들어, target="_blank"팝업이 성공적으로 열리면 리턴 false하면 링크 동작이 차단되고 그렇지 않으면 팝업이 차단되면 true기본 동작 (새 _blank 창 열기)으로 돌아가서 계속됩니다. .

<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >

이렇게하면 작동하면 팝업이 표시되고 그렇지 않으면 _blank 창이 나타납니다.

팝업이 열리지 않으면 다음을 수행 할 수 있습니다.

  • 예제와 같이 빈 창을 열고 계속하십시오.
  • 가짜 팝업 (페이지 내부의 iframe)을 엽니 다.
  • 사용자에게 알립니다 ( "이 사이트에 팝업을 허용하십시오").
  • 빈 창을 열고 사용자에게 알리십시오.

감사합니다. 일했다!
Bcktr

8

Google의 oauth JavaScript API에서 :

http://code.google.com/p/google-api-javascript-client/wiki/Authentication

읽는 영역을 참조하십시오.

인증 설정

클라이언트의 OAuth 2.0 구현은 팝업 창을 사용하여 사용자에게 응용 프로그램에 로그인하고 승인하라는 메시지를 표시합니다. gapi.auth.authorize에 대한 첫 번째 호출은 팝업 창을 간접적으로 열 때 팝업 차단기를 트리거 할 수 있습니다. 인증 차단시 팝업 차단기가 트리거되지 않도록하려면 클라이언트가로드 될 때 gapi.auth.init (callback)을 호출하십시오. 라이브러리가 인증 전화를 걸 준비가되면 제공된 콜백이 실행됩니다.

즉각적인 응답이 있는지 설명하는 방법에서 위의 실제 답변과 관련이 있다고 생각하면 팝업 경보가 작동하지 않습니다. "gapi.auth.init"는 API가 즉시 발생하도록합니다.

실용적인 응용 프로그램

npm의 노드 패스포트와 각 공급자에 대한 다양한 패스포트 패키지를 사용하여 오픈 소스 인증 마이크로 서비스를 만들었습니다. 나는 다시 리디렉션 URL을 제공하는 타사에 대한 표준 리디렉션 접근 방식을 사용했습니다. 이것은 프로그래밍 방식이므로 로그인 / 가입 및 특정 페이지에서 다른 곳으로 리디렉션 할 수 있습니다.

github.com/sebringj/athu

passportjs.org


3

여러 솔루션을 시도했지만 실제로는 모든 브라우저에서 나를 위해 일한 유일한 솔루션입니다.

let newTab = window.open(); newTab.location.href = url;


2
팝업 차단기를 사용하도록 설정 한 사용자에게는 작동하지 않습니다.
Alejandro Vales

무엇 url입니까? 할당되지 않았습니다.
shinriyo

@shinriyo url은 액세스하려는 모든 페이지에 대한 링크입니다. 예를 들어http://example.com
pomobc

@AlejandroVales 팝업 차단기가 활성화되어 있으며 작동합니다. 문제는 window.open()프로그래밍 방식으로 새 창을 열 수 없으며 필요한 경우 그 대답이 옵션 중 하나라는 것입니다. newTab변수를 사용하면 window.open()나중에 참조 할 수 있으며 url필요에 따라 삽입 할 수 있습니다 . 필자의 경우 url의 URL을 입력하면 입력 한 URL에서 새 탭이 열립니다.
stanimirsp

0

콜백이 성공적으로 반환되지 않으면 새 페이지를 만들고 싶지 않았으므로 사용자 클릭 을 시뮬레이트 하기 위해이 작업을 수행했습니다 .

function submitAndRedirect {
  apiCall.then(({ redirect }) => {
      const a = document.createElement('a');
      a.href = redirect;
      a.target = '_blank';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
  });
}

3
Chrome 62에서 작동하지 않습니다. 팝업 (페이지)이 차단되었습니다.
s.ermakovich

1
네 당신 말이 맞습니다-나는 또한 이것이 일관성이 없다는 것을 발견했습니다. 내 API 호출 동기 만드는 끝났다
user3479425

-8

이것을 제거하는 가장 쉬운 방법은 다음과 같습니다.

  1. document.open ()을 사용하지 마십시오.
  2. 대신 this.document.location.href = location을 사용하십시오. location은로드 할 URL입니다.

예 :

<script>
function loadUrl(location)
{
this.document.location.href = location;
}</script>

<div onclick="loadUrl('company_page.jsp')">Abc</div>

이것은 나를 위해 아주 잘 작동했습니다. 건배


2
새 탭에서 URL을 여는 것은 어떻습니까?
3 규칙
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.