it-swarm-vi.com

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

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

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

442
zing ming

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 lĩnh vực này được để trống. Vui lòng đảm bảo rằng ứng dụng của bạn có thể xử lý việc này hành vi.

Để 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ư tài liệu nói để sửa lỗi 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>
229
Ryan

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ỉ vào khối mã nếu fragment#_=_.
  2. Kiểm tra xem trình duyệt có hỗ trợ phương thức HTML5 window.replaceState không .
    1. Làm sạch URL bằng cách tách trên # và chỉ lấy phần đầu tiên.
    2. Nói với history để thay 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 băm thành chuỗi trống. Đây là một dự phòng kém vì nó vẫn để lại 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 trở lại #_-_

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

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

99
PapaSierra

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
  }
})
57
likebeats

Đ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 một lỗ hổng bảo mật tiềm năng.

Một số trình duyệt sẽ nối đoạn băm từ 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 bản thân nó có một đoạn băm).

Ví dụ: nếu example1.com trả về một chuyển hướng đến example2.com, thì một trình duyệt sẽ truy cập 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 đến tập lệnh trên example2.com.

Vì có thể có một luồng chuyển hướng auth sang luồng khác, nên nó sẽ 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 cho người 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 khách hàng của URL kết quả là quan tâm, có thể sử dụng window.location.hash (hoặc thậm chí chuyển hướng phía máy chủ của bạn) để xóa vi phạm nhân vật.

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

33
Mark Murphy

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 = "";
10
mixmasteralan

Bạn cũng có thể chỉ định hàm băm của riêng mình trên tham số redirect_uri 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, ví dụ: /api/account/callback#home. Khi bạn được chuyển hướng trở lại, ít nhất nó sẽ là 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).

9
pkiddie

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>
8
Jeremy Whitt

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), bởi 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 trả về với #_=_, điều đó 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ó.

8
Sándor Tóth

Đ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 JS với các URL hashbang (/ #! /), Ví dụ: Góc cạnh. 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
6
neemzy

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 JavaScript bị vô hiệu hóa và hoàn toàn chuyển hướng đăng nhập dựa trên. 

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.

5
Sebastian Tusk

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(/#.*/, '');
}
4
neokio

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

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
Slawomir

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 tuần này Tình yêu dành cho nhà phát triển hoạt động bài đăng trên blog để biết thông báo.

2
Dhiren Patel

Đố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>";        
}
2
Eng Cy

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

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 không có "#_=_". Có vẻ như khi chúng ta áp dụng cá thể passporJS làm phần mềm trung gian cho cá thể 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. 

1
Krishna

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. Điều này dường như được khuyến nghị hành vi .

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

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
Nanoripper

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 ), do đó không liên quan đến khớp tuyến.

0
rcomblen

Đ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
Akintunde-Rotimi