Gọi lại Facebook sẽ thêm '# _ = _' vào URL trả về


479

Gọi lại Facebook đã bắt đầu nối thêm #_=_dấu gạch dưới vào URL trả về

Có ai biết tại sao không? Giải pháp là gì?


35
Bất cứ ý tưởng làm thế nào facebook thêm các nhân vật này? Facebook chuyển hướng đến trình xử lý của tôi, nơi tôi sau đó xử lý chuyển hướng đến url trả về, nhưng các ký tự vẫn được gắn vào url.
Ben Foster

4
@BenFoster Tôi nghĩ bạn sẽ tìm thấy nếu bạn sử dụng Fiddler hoặc tương tự như khi FB chuyển hướng đến trình xử lý của bạn, #_=_đúng chỗ, ngay cả khi bạn thực hiện Response.Redirectđến nơi bạn thực sự muốn làm, trình duyệt vẫn duy trì hàm băm , đó là lý do tại sao chỉ có cách giải quyết phía khách hàng được đề xuất bên dưới sẽ hoạt động.
AakashM

17
2017, thật là tuyệt vời
Ejonas GGgg

6
Tháng 5 năm 2017, vẫn ....
Mirko

5
Tháng 3 năm 2018..yep vẫn xảy ra
John Rogerson

Câu trả lời:


239

thông qua Cập nhật nền tảng của Facebook :

Thay đổi hành vi chuyển hướng phiên

Tuần này, chúng tôi đã bắt đầu thêm một đoạn # ____ = ____ vào redirect_uri khi trường này được để trống. Hãy đảm bảo rằng ứng dụng của bạn có thể xử lý hành vi này.

Để ngăn chặn điều này, hãy đặt redirect_uri trong yêu cầu url đăng nhập của bạn như sau: (sử dụng Facebook php-sdk)

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

CẬP NHẬT

Trên đây là chính xác như các tài liệu nói để khắc phục điều này. Tuy nhiên, giải pháp tài liệu của Facebook không hoạt động. Vui lòng xem xét để lại nhận xét về bài đăng trên blog Cập nhật nền tảng Facebook và theo dõi lỗi này để có câu trả lời tốt hơn. Cho đến lúc đó, hãy thêm những điều sau vào thẻ head của bạn để giải quyết vấn đề này:

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

Hoặc một sự thay thế chi tiết hơn (cảm ơn 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
lĩnh vực nào được để trống? Điều này rất khó hiểu
user210504

11
@Ryan Cập nhật gần như hoạt động với tôi, tôi vẫn nhận được một hàm băm (/ #) ở cuối. Không hài lòng với FB.
LenPopLilly

2
Tôi vẫn nhận được / # là tốt. có ai cập nhật ở đây không? để xóa #
Tian Loon

6
Giải pháp này sẽ xóa hàm băm: <script type = "text / javascript"> var idx = window.location.toString (). IndexOf ("# _ = _"); if (idx> 0) {window.location = window.location.toString (). chuỗi con (0, idx); } </ script> Chỉ cần chắc chắn đây là thẻ đầu tiên trong phần tử head.
Gorgi Rankovski

1
Tôi nhận thấy báo cáo lỗi của bạn ở đây: developers.facebook.com/bugs/1424488987806270 Tôi cũng đã thử tìm kiếm "Fragment request_uri" với kết quả tương tự.
Ryan

115

TL; DR

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

Phiên bản đầy đủ với hướng dẫn từng bước

// 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 = "";

    }

}

Từng bước một:

  1. Chúng tôi sẽ chỉ nhận được vào khối mã nếu fragment#_=_.
  2. Kiểm tra xem trình duyệt có hỗ trợ window.replaceStatephương thức HTML5 không .
    1. Làm sạch URL bằng cách tách #và chỉ lấy phần đầu tiên.
    2. Yêu cầu historythay thế trạng thái trang hiện tại bằng URL sạch. Điều này sửa đổi mục lịch sử hiện tại thay vì tạo một mục mới. Điều này có nghĩa là các nút quay lại và chuyển tiếp sẽ hoạt động theo cách bạn muốn. ;-)
  3. Nếu trình duyệt không hỗ trợ các phương thức lịch sử HTML 5 tuyệt vời thì bạn chỉ cần dọn sạch URL một cách tốt nhất có thể bằng cách đặt hàm băm thành chuỗi trống. Đây là một dự phòng kém vì nó vẫn để lại một dấu băm (example.com/#) và nó cũng thêm một mục lịch sử, vì vậy nút quay lại sẽ đưa bạn quay lại #_-_.

Tìm hiểu thêm về history.replaceState.

Tìm hiểu thêm về window.location.


2
Làm việc hoàn hảo cho tôi quá. Các giải pháp khác được loại bỏ bất kỳ tham số truy vấn.
AdeelMufti

Nó cũng làm điều tương tự với google omniauth, vì vậy tôi gặp lỗi không có tuyến nào khớp, nó sẽ thêm # (hashtag) sau khi yêu cầu uri https: //.....herokua‌ pp.com/auth/google_oa‌ uth2 / gọi lại? state = 1 9feaacfe23423jh5jhhGS DFwb419049ebb18dabdf8 & code = 4 / glrY3-mSlTzwe rwERTEG334eXcn3hOSxGu c51BAlglPa4AU #
Shalafister của

Làm việc cho tôi tốt hơn giải pháp của @Ryan, vì nó không xóa truy vấn.
olivmir

Giải pháp này hoạt động tốt hơn giải pháp của Ryan. Tôi chuyển một số tham số cho url sau khi nó đi qua xác thực của facebook và giải pháp của Ryan, vì một số lý do chỉ xóa mọi tham số khỏi url. Giải pháp này hoạt động hoàn hảo trong trường hợp của tôi.
BlueSun3k1

59

nếu bạn muốn xóa "#" còn lại khỏi 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 * /} hoạt động.
ISHITOYA Kentaro

1
tôi sử dụng mã này bằng cách thay đổi e.preventDefault (); đến event.preventDefault ();
printf

Mã này đang giả sử jQuery và một trình lắng nghe sự kiện onWindowReady lấy tham số e.
Jason Sperske

49

Điều này đã được Facebook thực hiện bởi thiết kế vì lý do bảo mật. Dưới đây là lời giải thích từ Eric Osgood, thành viên Nhóm Facebook:

Điều này đã được đánh dấu là "theo thiết kế" bởi vì nó ngăn ngừa lỗ hổng bảo mật tiềm ẩn.

Một số trình duyệt sẽ nối đoạn băm từ URL vào cuối URL mới mà chúng đã được chuyển hướng (nếu URL mới đó không có đoạn băm).

Ví dụ: nếu example1.com trả về chuyển hướng đến example2.com, thì trình duyệt sẽ đến example1.com # abc sẽ truy cập example2.com # abc và nội dung phân đoạn băm từ example1.com có ​​thể truy cập được vào tập lệnh trên example2 .com.

Vì có thể có một luồng chuyển hướng auth sang một luồng khác, nên có thể có dữ liệu xác thực nhạy cảm từ một ứng dụng có thể truy cập vào một ứng dụng khác.

Điều này được giảm nhẹ bằng cách nối thêm một đoạn băm mới vào URL chuyển hướng để ngăn chặn hành vi trình duyệt này.

Nếu tính thẩm mỹ hoặc hành vi phía máy khách của URL kết quả là mối quan tâm, thì có thể sử dụng window.location.hash (hoặc thậm chí là chuyển hướng phía máy chủ của bạn) để xóa các ký tự vi phạm.

Nguồn: https://developers.facebook.com/bugs/318390728250352/


9
Đây là câu trả lời duy nhất thực sự giải thích lý do tại sao điều này xảy ra, cảm ơn, tôi nghĩ rằng tôi sẽ để lại những ký tự vi phạm trong các url của mình mà tôi biết chúng không phải là vấn đề.
stephenmurdoch

1
Điều này cũng được Tumblr thực hiện trong các chuyển hướng của họ. (tính đến giữa năm 19) Cảm ơn bạn đã chỉ ra lời giải thích của FB. Dễ dàng giải quyết trong ứng dụng Hộ chiếu đơn giản bằng cách chỉ chuyển hướng thành công sang "/ #" thay vì chỉ "/" (điều này giải thích lý do tại sao tôi thấy nhiều octothorps trên web hơn, tôi nghĩ rằng ...)
RL Brown

10

Không chắc chắn lý do tại sao họ làm điều này nhưng, bạn có thể khắc phục điều này bằng cách đặt lại hàm băm ở đầu trang của bạn:

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

9

Bạn cũng có thể chỉ định hàm băm của riêng mình trên redirect_uritham số cho cuộc gọi lại Facebook, điều này có thể hữu ích trong một số trường hợp nhất định, vd /api/account/callback#home. Khi bạn được chuyển hướng trở lại, ít nhất nó sẽ là một hàm băm tương ứng với một tuyến đã biết nếu bạn đang sử dụng backbone.js hoặc tương tự (không chắc chắn về jquery mobile).


8

Facebook sử dụng một khung và bên trong nó mọi chức năng sử dụng giao tiếp AJAX. Vấn đề lớn nhất trong trường hợp này là duy trì trạng thái trang hiện tại. Theo tôi hiểu, Facebook đã quyết định sử dụng các neo giả lập. Điều này có nghĩa là nếu bạn đã nhấp vào một nơi nào đó, họ sẽ mô phỏng nó như một mỏ neo bên trong trang của bạn và khi giao tiếp AJAX bắt đầu, họ cũng thay đổi bit neo của URL của bạn.

Giải pháp này giúp bạn bình thường khi bạn cố tải lại trang (không phải ENTER, nhấn F5), vì trình duyệt của bạn gửi toàn bộ URL có neo đến máy chủ Facebook. Do đó, Facebook chọn trạng thái mới nhất (những gì bạn thấy) và sau đó bạn có thể tiếp tục từ đó.

Khi gọi lại với #_=_nó có nghĩa là trang đã ở trạng thái cơ bản trước khi rời khỏi nó. Vì neo này được trình duyệt phân tích cú pháp, bạn không cần phải lo lắng về nó.


2
Nếu bạn có một khung javascript như xương sống hoặc than hồng thì đó là một vấn đề vì mọi thứ sau khi băm được bộ định tuyến diễn giải
Rudi

1
Mã định danh đoạn URL ("neo") không được gửi đến trình duyệt theo yêu cầu. Ngoài ra, câu hỏi này là về OAuth, không phải về trang web máy tính để bàn chính. Lý do cho điều này là bảo mật OAuth - ngăn chặn các cuộc tấn công do tạo ra một URI chuyển hướng độc hại.
AndrewF

8

Khó chịu lớn, đặc biệt là đối với các ứng dụng phân tích URI và không chỉ đọc $ _GET ... Đây là bản hack tôi đã ném cùng nhau ... Tận hưởng!

<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>

Hãy cẩn thận về việc đưa ra các giả định khi phân tích bất kỳ dữ liệu nào bạn không tạo. Số nhận dạng phân đoạn URI được xác định sớm nhất là RFC 1738 (năm 1994), vì vậy nếu bạn sử dụng trình phân tích cú pháp URI chính xác, điều này sẽ không bao giờ là vấn đề.
AndrewF

6

Điều này có thể trở thành một vấn đề nghiêm trọng nếu bạn đang sử dụng khung công tác JS với các URL hashbang (/ #! /), Ví dụ như Angular. Thật vậy, Angular sẽ coi các URL có đoạn không băm là không hợp lệ và gây ra lỗi:

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

Nếu bạn đang ở trong trường hợp như vậy (và chuyển hướng đến thư mục gốc của bạn), thay vì thực hiện:

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

Đơn giản chỉ cần làm:

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

1.2+, điều này hoạt động tuyệt vời. Đối với 1.0 trở xuống, hãy sử dụng window.location.hash = '';
Pradeep Mahdevu

1
Có, tôi chỉ thử nghiệm điều này vào ngày 1.2, cảm ơn về thông số kỹ thuật!
neemzy

Và sau đó là chế độ html5
rocketspacer

5

Tôi không thấy vấn đề này liên quan đến facebook AJAX như thế nào. Trong thực tế, vấn đề cũng xảy ra với các thông tin đăng nhập dựa trên JavaScript bị vô hiệu hóa và hoàn toàn chuyển hướng.

Một ví dụ trao đổi với facebook:

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#_  

Chỉ xảy ra với Firefox cho tôi.


4

Thêm điều này vào trang chuyển hướng của tôi đã khắc phục sự cố cho tôi ...

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

1
điều này gây ra thay đổi vị trí cửa sổ, bắt đầu làm mới trang
rpearce

3

Với bộ định tuyến ui góc và góc, bạn có thể khắc phục điều này

    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 ...
    });
});

không hoạt động ở đây - tuyến đường thay đổi trước khi quy tắc () được áp dụng
Maël Nison

3

Nếu bạn đang sử dụng bộ định tuyến vue, bạn có thể thêm vào danh sách các tuyến đường:

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

2

Một thay đổi đã được giới thiệu gần đây về cách Facebook xử lý các chuyển hướng phiên. Xem "Thay đổi hành vi chuyển hướng phiên" trong bài đăng trên blog Hoạt động của nhà phát triển tình yêu trong tuần này để biết thông báo.


1
Tôi không chắc chắn, anh ta đang đề cập đến điều gì ở đây
user210504

2

Đối với tôi, tôi thực hiện chuyển hướng JavaScript sang một trang khác để thoát khỏi #_=_. Những ý tưởng dưới đây nên hoạt động. :)

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

Tôi nghĩ đây không phải là một ý tưởng hay vì bạn đang tạo ra nhiều yêu cầu vô ích
Jacek Pietal 21/07/2016

1

Một cách giải quyết phù hợp với tôi (sử dụng Backbone.js) là thêm "# /" vào cuối URL chuyển hướng được chuyển đến Facebook. Facebook sẽ giữ lại đoạn được cung cấp và không nối thêm "_ = _".

Khi trở về, Backbone sẽ xóa phần "# /". Đối với AngularJS, thêm "#!" URL trả về sẽ hoạt động.

Lưu ý rằng số nhận dạng phân đoạn của URL gốc được bảo toàn khi chuyển hướng (thông qua mã trạng thái HTTP 300, 301, 302 và 303) bởi hầu hết các trình duyệt, trừ khi URL chuyển hướng cũng có số nhận dạng phân đoạn. Đây dường như là hành vi được đề nghị .

Nếu bạn sử dụng tập lệnh xử lý chuyển hướng người dùng ở nơi khác, bạn có thể nối "#" vào URL chuyển hướng ở đây để thay thế mã định danh phân đoạn bằng một chuỗi trống.


1

Tôi biết câu trả lời này là muộn, nhưng nếu bạn đang sử dụng Passportjs, bạn có thể muốn thấy điều này.

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

Tôi đã viết phần mềm trung gian này và áp dụng nó để thể hiện máy chủ và URL ban đầu tôi nhận được là không có "#_=_". Có vẻ như khi chúng ta áp dụng thể hiện của passporJS làm phần mềm trung gian cho phiên bản máy chủ, nó không lấy các ký tự đó, nhưng chỉ hiển thị trên thanh địa chỉ của trình duyệt của chúng tôi.


3
"# _ = _" nó chỉ khả dụng trên máy khách. Đánh giá: en.wikipedia.org/wiki/Fragment_identifier
viêm ald

1

Tôi cũng sử dụng cái này để xóa biểu tượng '#'.

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

0

Sử dụng Angular 2 (RC5) và các tuyến dựa trên hàm băm, tôi làm điều này:

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

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

Theo tôi hiểu, =ký tự trong tuyến được hiểu là một phần của định nghĩa tham số tuyến tùy chọn (xem https://angular.io/docs/ts/latest/guide/router.html#!#optional-route-parameter ) , vì vậy không tham gia vào tuyến đường phù hợp.


0

Dành cho người dùng SDK PHP

Tôi đã khắc phục vấn đề đơn giản bằng cách loại bỏ phần phụ trước khi chuyển tiếp.

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

0

Điều này sẽ xóa các ký tự được thêm vào url của bạn

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

0

Giải pháp đơn giản và dễ dàng nhất để xóa "# _ = _" (PHP):

Thay vì "tiêu đề (" Vị trí: xxx.php ");" để sử dụng "echo (" location.href = 'xxx.php'; ");"

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.