Facebook 콜백이 '# _ = _'을 반환 URL에 추가


479

Facebook 콜백에서 #_=_해시 밑줄을 반환 URL에 추가하기 시작했습니다.

아무도 이유를 알고 있습니까? 해결 방법이 무엇입니까?


35
모든 아이디어를 어떻게 페이스 북은 이러한 문자를 추가? Facebook은 내 처리기로 리디렉션하여 반환 URL 로의 리디렉션을 처리하지만 문자는 여전히 URL에 추가됩니다.
벤 포스터

4
난 당신이 피들러 또는 FB는 핸들러에 redurects 때 유사한 사용하는 경우가 찾을 생각 @BenFoster, (가) #_=_당신이 할 경우에도 다음 장소에 Response.Redirect당신이 실제로하고 싶은 곳으로, 브라우저는 해시를 유지하는 이유입니다, 아래 제안 된 클라이언트 측 해결 방법 만 작동합니다.
AakashM

17
2017, 뻐꾸기
Ejonas GGgg

6
2017 년 5 월, 여전히 ....
Mirko

5
3 월 2018..yep가 여전히 발생
존 로저 슨

답변:


239

Facebook의 플랫폼 업데이트 를 통해 :

세션 리디렉션 동작 변경

이번 주에이 필드를 비워두면 redirect_uri에 조각 # ____ = ____을 추가하기 시작했습니다. 앱이이 동작을 처리 할 수 ​​있는지 확인하십시오.

이를 방지하려면 로그인 URL 요청에서 redirect_uri를 다음과 같이 설정하십시오 (Facebook php-sdk 사용).

$facebook->getLoginUrl(array('redirect_uri' => $_SERVER['SCRIPT_URI'],'scope' => 'user_about_me'));

최신 정보

위의 내용은 설명서 에서이 문제를 해결하기위한 내용과 동일합니다. 그러나 Facebook의 문서화 된 솔루션이 작동하지 않습니다. Facebook 플랫폼 업데이트 블로그 게시물 에 의견을 남기고이 버그 에 따라 더 나은 답변을 얻으 십시오 . 그때까지이 문제를 해결하려면 헤드 태그에 다음을 추가하십시오.

<script type="text/javascript">
    if (window.location.hash && window.location.hash == '#_=_') {
        window.location.hash = '';
    }
</script>

또는 더 자세한 대안 (감사합니다 niftylettuce ) :

<script type="text/javascript">
    if (window.location.hash && window.location.hash == '#_=_') {
        if (window.history && history.pushState) {
            window.history.pushState("", document.title, window.location.pathname);
        } else {
            // Prevent scrolling by storing the page's current scroll offset
            var scroll = {
                top: document.body.scrollTop,
                left: document.body.scrollLeft
            };
            window.location.hash = '';
            // Restore the scroll offset, should be flicker free
            document.body.scrollTop = scroll.top;
            document.body.scrollLeft = scroll.left;
        }
    }
</script>

10
어떤 필드가 비어 있습니까? 이것은 매우 비밀입니다
user210504

11
@Ryan Update는 거의 나를 위해 작동하지만 끝에 여전히 해시 (/ #)가 나타납니다. FB에 만족하지 않습니다.
LenPopLilly

2
여전히 / #도 얻습니다. 누구 여기 업데이트? 제거 # 얻을
티안 룬

6
이 솔루션은 해시를 지 웁니다. <script type = "text / javascript"> var idx = window.location.toString (). indexOf ( "# _ = _"); if (idx> 0) {window.location = window.location.toString (). substring (0, idx); } </ script> head 요소의 첫 번째 태그 여야합니다.
Gorgi Rankovski

1
나는 버그 보고서를 여기에서 발견했다 : developers.facebook.com/bugs/1424488987806270 또한 같은 결과로 "fragment request_uri"를 검색하려고 시도했다.
Ryan

115

TL; DR

if (window.location.hash === "#_=_"){
    history.replaceState 
        ? history.replaceState(null, null, window.location.href.split("#")[0])
        : window.location.hash = "";
}

단계별 지침이 포함 된 정식 버전

// Test for the ugliness.
if (window.location.hash === "#_=_"){

    // Check if the browser supports history.replaceState.
    if (history.replaceState) {

        // Keep the exact URL up to the hash.
        var cleanHref = window.location.href.split("#")[0];

        // Replace the URL in the address bar without messing with the back button.
        history.replaceState(null, null, cleanHref);

    } else {

        // Well, you're on an old browser, we can get rid of the _=_ but not the #.
        window.location.hash = "";

    }

}

단계별 :

  1. fragmentis 인 경우에만 코드 블록으로 들어갑니다 #_=_.
  2. 브라우저가 HTML5 window.replaceState메소드를 지원하는지 확인하십시오 .
    1. #첫 번째 부분 만 분리하여 가져 와서 URL을 정리하십시오 .
    2. 에게 history깨끗한 URL과 현재 페이지 상태를 바꿀 수 있습니다. 새 항목을 만들지 않고 현재 기록 항목을 수정합니다. 이것이 의미하는 바는 뒤로 및 앞으로 버튼이 원하는대로 작동한다는 것입니다. ;-)
  3. 브라우저가 멋진 HTML 5 기록 방법을 지원하지 않으면 해시를 빈 문자열로 설정하여 최대한 URL을 정리하십시오. 이것은 여전히 ​​후행 해시 (example.com/#)를 남기고 기록 항목을 추가하기 때문에 좋지 않은 대체 #_-_입니다.

에 대해 자세히 알아보십시오 history.replaceState.

에 대해 자세히 알아보십시오 window.location.


2
나도 완벽하게 일했다. 다른 솔루션은 모든 쿼리 매개 변수를 제거합니다.
AdeelMufti

Google omniauth와 동일한 작업을 수행하므로 경로와 일치하는 오류가 없습니다. 요청 후 # (hashtag)를 추가하십시오 https : //.....herokua‌pp.com/auth/google_oa‌uth2/callback? state = 1‌9feaacfe23423jh5jhhGS‌DFwb419049ebb18dabdf8‌ & code = 4 / glrY3-mSlTzwe‌rwERTEG334eXcn3hOSxGu‌c51BAlglPa4AU #
Shalafister 's

쿼리를 삭제하지 않기 때문에 @Ryan의 솔루션보다 나에게 더 효과적이었습니다.
olivmir

이 솔루션은 Ryan의 솔루션보다 더 효과적이었습니다. 페이스 북의 인증과 Ryan의 솔루션을 통해 URL에 일부 매개 변수를 전달합니다. 어떤 이유로 든 URL에서 모든 매개 변수를 제거합니다. 이 솔루션은 제 경우에는 완벽하게 작동합니다.
BlueSun3k1

59

URL에서 나머지 "#"을 제거하려는 경우

$(window).on('load', function(e){
  if (window.location.hash == '#_=_') {
    window.location.hash = ''; // for older browsers, leaves a # behind
    history.pushState('', document.title, window.location.pathname); // nice and clean
    e.preventDefault(); // no page reload
  }
})

6
$ (window) .on ( 'load', function (e) {/ * likebeats 's code * /} 작동
ISHITOYA Kentaro

1
이 코드를 변경하여 사용합니다. e.preventDefault (); event.preventDefault ()로;
printf

이 코드는 jQuery와 onWindowReady 이벤트 리스너가 인수를 취하는 것으로 가정합니다 e.
Jason Sperske

49

이것은 보안상의 이유로 Facebook에서 의도적으로 구현 한 것입니다. Facebook 팀 멤버 인 Eric Osgood의 설명은 다음과 같습니다.

잠재적 인 보안 취약점을 방지하기 때문에 '설계에 따라'로 표시되었습니다.

일부 브라우저는 URL에서 해시 조각을 리디렉션 된 새 URL 끝에 추가합니다 (해당 URL 자체에 해시 조각이없는 경우).

예를 들어 example1.com이 example2.com으로 리디렉션을 반환하면 example1.com # abc로 이동하는 브라우저는 example2.com # abc로 이동하고 example1.com의 해시 조각 컨텐츠는 example2의 스크립트에 액세스 할 수 있습니다. .com.

하나의 인증 흐름을 다른 인증 흐름으로 리디렉션 할 수 있으므로 한 앱의 민감한 인증 데이터를 다른 앱에 액세스 할 수 있습니다.

이 브라우저 동작을 방지하기 위해 리디렉션 URL에 새 해시 조각을 추가하면 완화됩니다.

결과 URL의 미학 또는 클라이언트 측 동작이 문제가되는 경우 window.location.hash (또는 사용자 자신의 서버 측 리디렉션)를 사용하여 문제가있는 문자를 제거 할 수 있습니다.

출처 : https://developers.facebook.com/bugs/318390728250352/


9
이것이 실제로 왜 이런 일이 발생하는지 설명하는 유일한 대답입니다. 감사합니다. 문제가되지 않는다는 것을 알았으므로 문제가되는 URL을 내 URL에 남겨 두겠습니다.
stephenmurdoch

1
이것은 또한 Tumblr의 리디렉션에서 구현됩니다. (19 년 중반 현재) FB 설명을 지적 해 주셔서 감사합니다. 단순히 "/"대신 "/ #"로의 성공적인 리디렉션을 가리키면 단순한 Passport 앱에서 쉽게 해결됩니다 (웹에서 더 많은 후행 문어를 보는 이유를 설명합니다 ...)
RL Brown

10

왜 이런 일을하는지 확실하지 않지만 페이지 상단에서 해시를 재설정하여이 문제를 해결할 수 있습니다.

if (window.location.hash == "#_=_")
  window.location.hash = "";

9

redirect_uriFacebook 콜백 의 매개 변수 에 고유 한 해시를 지정할 수도 있습니다 (예 :) /api/account/callback#home. 다시 리디렉션 할 때 backbone.js 또는 이와 유사한 것을 사용하는 경우 알려진 경로에 해당하는 해시가 될 것입니다 (jquery mobile에 대해서는 확실하지 않음).


8

Facebook은 프레임을 사용하며 그 내부는 AJAX 통신을 사용하여 작동합니다. 이 경우 가장 큰 문제는 현재 페이지 상태를 유지하는 것입니다. 내가 아는 한, Facebook은 시뮬레이션 앵커를 사용하기로 결정했습니다. 즉, 어딘가에서 클릭하면 페이지 내부의 앵커로 시뮬레이션하고 AJAX 통신이 시작되면 URL의 앵커 비트도 변경됩니다.

F5브라우저가 앵커와 함께 전체 URL을 Facebook 서버로 전송하기 때문에이 솔루션은 일반적으로 페이지를 다시로드하려고 할 때 (ENTER가 아닌을 누르는 경우 ) 도움이됩니다 . 따라서 Facebook은 최신 상태 (표시되는 내용)를 선택하여 계속 진행할 수 있습니다.

콜백이 함께 반환되면 #_=_페이지가 페이지를 떠나기 전에 기본 상태에 있었음을 의미합니다. 이 앵커는 브라우저에 의해 구문 분석되므로 걱정할 필요가 없습니다.


2
백본이나 엠버와 같은 자바 스크립트 프레임 워크를 가지고 있다면 라우터가 해시를 해석 한 후 모든 것이 문제가됩니다
Rudi

1
URL 조각 식별자 ( "앵커")는 요청시 브라우저로 전송되지 않습니다 . 또한이 질문은 주 데스크톱 사이트가 아니라 OAuth에 관한 것입니다. 그 이유 는 악의적 인 리디렉션 URI를 만들어 공격을 방지하는 OAuth 보안 입니다.
AndrewF

8

특히 URI를 구문 분석하고 $ _GET을 읽지 않는 앱의 경우 성가신 일입니다 ... 여기에 함께 던진 해킹이 있습니다. 즐기십시오!

<html xmlns:fb='http://www.facebook.com/2008/fbml'>
<head>
        <script type="text/javascript">
        // Get rid of the Facebook residue hash in the URI
        // Must be done in JS cuz hash only exists client-side
        // IE and Chrome version of the hack
        if (String(window.location.hash).substring(0,1) == "#") {
                window.location.hash = "";
                window.location.href=window.location.href.slice(0, -1);
                }
        // Firefox version of the hack
        if (String(location.hash).substring(0,1) == "#") {
                location.hash = "";
                location.href=location.href.substring(0,location.href.length-3);
                }
        </script>
</head>
<body>
URI should be clean
</body>
</html>

작성하지 않은 데이터를 구문 분석 할 때 가정 할 때주의하십시오. URI 조각 식별자는 RFC 1738 (1994 년)에 초기에 지정되었으므로 올바른 URI 파서를 사용하면 결코 문제가되지 않습니다.
AndrewF

6

Angular와 같이 hashbang (/ #! /) URL과 함께 JS 프레임 워크를 사용하는 경우 심각한 문제가 될 수 있습니다. 실제로 Angular는 hashbang이 아닌 조각이있는 URL을 유효하지 않은 것으로 간주하고 오류를 발생시킵니다.

Error: Invalid url "http://example.com/#_=_", missing hash prefix "#!".

그러한 경우에 다음을 수행하는 대신 다음과 같이 도메인 루트로 리디렉션하십시오.

window.location.hash = ''; // goes to /#, which is no better

간단히 :

window.location.hash = '!'; // goes to /#!, which allows Angular to take care of the rest

1.2 이상, 이것은 훌륭하게 작동합니다. 1.0 이하에서는 window.location.hash = '';
Pradeep Mahdevu

1
예, 사양 덕분에 1.2에서만 테스트했습니다!
neemzy

그리고 html5 모드가 있습니다
rocketspacer

5

이 문제가 페이스 북 AJAX와 어떤 관련이 있는지 모르겠습니다. 실제로이 문제는 JavaScript가 비활성화되고 순수하게 리디렉션 기반 로그인으로 발생합니다.

페이스 북과의 교환 예 :

1. GET <https://www.facebook.com/dialog/oauth?client_id=MY_APP_ID&scope=email&redirect_uri=MY_REDIRECT_URL> RESPONSE 302 Found Location: <https://www.facebook.com/connect/uiserver.php?[...]>  
2. GET <https://www.facebook.com/connect/uiserver.php?[...]> RESPONSE 302 Found MY_REDIRECT_URL?code=FB_CODE#_  
3. GET MY_REDIRECT_URL?code=FB_CODE#_  

나에게도 Firefox 만 있습니다.


4

내 리디렉션 페이지에 이것을 추가하면 문제가 해결되었습니다 ...

if (window.location.href.indexOf('#_=_') > 0) {
    window.location = window.location.href.replace(/#.*/, '');
}

1
이로 인해 창 위치가 변경되어 페이지 새로 고침이 시작됩니다.
rpearce

3

각도 및 각도 UI 라우터를 사용하면이 문제를 해결할 수 있습니다

    app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {

      // Make a trailing slash optional for all routes
      // - Note: You'll need to specify all urls with a trailing slash if you use this method.
      $urlRouterProvider.rule(function ($injector, $location) {
        /***
        Angular misbehaves when the URL contains a "#_=_" hash.

        From Facebook:
          Change in Session Redirect Behavior
          This week, we started adding a fragment #_=_ to the redirect_uri when this field is left blank.
          Please ensure that your app can handle this behavior.

        Fix:
          http://stackoverflow.com/questions/7131909/facebook-callback-appends-to-return-url#answer-7297873
        ***/
        if ($location.hash() === '_=_'){
          $location.hash(null);
        }

        var path = $location.url();

        // check to see if the path already has a slash where it should be
        if (path[path.length - 1] === '/' || path.indexOf('/?') > -1) {
          return;
        }
        else if (path.indexOf('?') > -1) {
          $location.replace().path(path.replace('?', '/?'));
        }
        else {
          $location.replace().path(path + '/');
        }
      });

      // etc ...
    });
});

여기서 작동하지 않습니다-rule ()이 적용되기 전에 경로가 변경됩니다.
Maël Nison

3

vue-router를 사용하는 경우 경로 목록에 추가 할 수 있습니다.

{
  path: '/_=_',
  redirect: '/', // <-- or other default route
},

2

최근 Facebook에서 세션 리디렉션을 처리하는 방식이 변경되었습니다. 공지에 대한 이번 주 Operation Developer Love 블로그 게시물 에서 "세션 리디렉션 동작 변경"을 참조하십시오 .


1
잘 모르겠습니다. 여기에서 무슨 말을하는지
user210504

2

나를 위해 JavaScript를 다른 페이지로 리디렉션하여 제거 #_=_합니다. 아래 아이디어는 효과가 있습니다. :)

function redirect($url){
    echo "<script>window.location.href='{$url}?{$_SERVER["QUERY_STRING"]}'</script>";        
}

이것은 여러 쓸모없는 요청을 생성하기 때문에 내 생각은 좋은 생각이 아니다
제이 섹 Pietal

1

Backbone.js를 사용하여 나를 위해 일한 해결 방법은 Facebook에 전달 된 리디렉션 URL 끝에 "# /"를 추가하는 것이 었습니다. Facebook은 제공된 조각을 유지하고 자체 "_ = _"를 추가하지 않습니다.

돌아 오면 Backbone은 "# /"부분을 제거합니다. AngularJS의 경우 "#!"추가 반환 URL로 작동합니다.

리디렉션 URL에 조각 식별자가없는 경우 원래 URL의 조각 식별자는 대부분의 브라우저에서 리디렉션 (HTTP 상태 코드 300, 301, 302 및 303을 통해)으로 유지됩니다. 이것은 권장되는 행동 인 것 같습니다 .

사용자를 다른 곳으로 리디렉션하는 핸들러 스크립트를 사용하는 경우 여기에서 리디렉션 URL에 "#"을 추가하여 조각 식별자를 빈 문자열로 바꿀 수 있습니다.


1

답장이 늦었다는 것을 알고 있지만, Passportjs를 사용하고 있다면 이것을보고 싶을 것입니다.

return (req, res, next) => {
    console.log(req.originalUrl);
    next();
};

이 미들웨어를 작성하여 서버 인스턴스를 표현하는 데 적용했으며 원래 URL은 "#_=_"입니다. passporJS의 인스턴스를 서버 인스턴스에 미들웨어로 적용하면 해당 문자를 사용하지 않지만 브라우저의 주소 표시 줄에서만 볼 수 있습니다.


3
"# _ = _"는 클라이언트에서만 사용할 수 있습니다. 검토 : en.wikipedia.org/wiki/Fragment_identifier
alditis

1

나는 이것을 사용하여 '#'기호를 삭제합니다.

<script type="text/javascript">
    if (window.location.hash && window.location.hash == '#_=_') {
        window.location.href = window.location.href.split('#_=_')[0];
    }
</script>

0

Angular 2 (RC5)와 해시 기반 경로를 사용하여 다음과 같이합니다.

const appRoutes: Routes = [
  ...
  {path: '_', redirectTo: '/facebookLoginSuccess'},
  ...
]

export const routing = RouterModule.forRoot(appRoutes, { useHash: true });

내가 이해 =하는 한 경로 의 문자는 선택적 경로 매개 변수 정의의 일부로 해석됩니다 ( https://angular.io/docs/ts/latest/guide/router.html#!#optional-route-parameters 참조 ) 경로 일치와 관련이 없습니다.


0

PHP SDK 사용자

전달하기 전에 여분의 부품을 제거하여 문제를 해결했습니다.

 $loginURL = $helper->getLoginUrl($redirectURL, $fbPermissions);
 $loginURL = str_replace("#_=_", "", $loginURL);
 header("Location: " . $loginURL);

0

이렇게하면 URL에 추가 된 문자가 제거됩니다.

<script type="text/javascript">
 var idx=window.location.toString().indexOf("#_=_"); 
   if (idx > 0) { 
     window.location = window.location.toString().substring(0, idx); 
   } 
</script>

0

"# _ = _"(PHP)를 제거하는 가장 쉽고 깨끗한 솔루션 :

"header ("Location : xxx.php ");"대신 "echo ("location.href = 'xxx.php'; ");"를 사용하려면

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.