2013-12-10 18 views
10

Tôi đang làm việc trên một chức năng cho phép người dùng đăng nhập trên trang web của tôi bằng tài khoản Google của họ.Đăng nhập bằng Google+ với sự cố gọi lại JavaScript

Mã của tôi dựa trên số Google documentation (các tùy chọn signIn() khác nằm trong thẻ meta).

function login() { 
    gapi.auth.signIn({'callback': 
    function (authResult) { 
     if (authResult['status']['signed_in']) { 
     console.log('Okay'); 
     }else { 
     console.log('Error'); 
     } 
    } 
    }); 
} 

Khi tôi gọi đăng nhập(), cửa sổ bật lên của Google xuất hiện, tôi chấp thuận điều khoản của đơn đăng ký và mọi thứ hoạt động tốt.

Nhưng callback được gọi hai lần:

  • trường hợp 1: Nếu tôi không bao giờ chấp nhận các ứng dụng cho phép sau đó gọi lại sẽ gọi tại buổi khai mạc của cửa sổ pop up VÀ khi tôi sẽ chấp nhận các điều khoản. Vì vậy, nó sẽ viết "Lỗi" và "Được rồi".
  • Trường hợp thứ hai: Nếu tôi đã phê duyệt các quyền, nó sẽ viết "Được rồi" hai lần.

Tôi đã thêm tùy chọn 'approvalprompt': 'force' vào hàm signIn(). Hàm gọi lại không còn được gọi hai lần nữa nhưng nó buộc người dùng chấp thuận các quyền của ứng dụng, ngay cả khi đã được phê duyệt trước đó. Vì vậy, nó không thân thiện với người dùng.

Có cách nào thân thiện với người dùng để phê duyệt quyền của ứng dụng một lần mà không có hai cuộc gọi lại không?

Cảm ơn bạn.

+0

bản sao có thể có của [Đăng nhập Google hai lần?] (Http://stackoverflow.com/questions/23020733/google-login-hitting-twice) –

+0

Dường như đây là vấn đề phổ biến. Có một câu trả lời ở đây: stackoverflow.com/questions/23020733/… - –

Trả lời

4

Cố gắng đăng ký cuộc gọi đầu tiên trong một số biến địa phương và sau đó xử lý nó

giải pháp nhanh chóng này giúp tôi:

function login() { 
    var initializedGoogleCallback = false 
    gapi.auth.signIn({ 
    'callback': function (authResult) { 
     if (!initializedGoogleCallback) { 
     // after first call other will be ignored 
     initializedGoogleCallback = true; 
     if (authResult['status']['signed_in']) { 
      console.log('Okay'); 
     } else { 
      console.log('Error'); 
     } 
     } 
    } 
    }); 
} 

bạn cũng có thể thêm mã sau đây trước khi gọi gapi.auth.signIn

window.removeEventListener('load') 
+0

Đó là một giải pháp tốt cảm ơn bạn! Nhưng tôi vẫn không biết tại sao chúng ta phải làm điều đó, nó giống như "gian lận". Có thể đó là lỗi hoặc chúng tôi không hiểu lý do. – sylvhama

+1

Tôi nghĩ lý do là trong thư viện google js. Nhưng google không cung cấp cách bình thường để loại bỏ tất cả các sự kiện trước đó trước khi gọi phương thức mới. Ngoài ra không có nguồn js để hiểu đầy đủ lý do và API cũng không mô tả điều này. – Panoptik

6

Tôi đang đối mặt với cùng một vấn đề: đăng nhập gọi lại được gọi hai lần trong trường hợp người dùng đã được cấp quyền; cách tiếp cận biến cục bộ (initializedGoogleCallback) không hoạt động đối với tôi vì nó chỉ gọi lại lần gọi khi người dùng đã cấp quyền truy cập, nhưng không gọi nó nếu người dùng là người mới. Sau một chút nghiên cứu (tôi đặc biệt là đào trong trang web bằng cách sử dụng g + auth) tôi nhận thấy rằng tất cả chúng sử dụng 'approvalprompt': 'force' và họ có người dùng đã cấp để tái đăng ký chính sách "Truy cập ngoại tuyến" mọi lúc. Ngay cả ví dụ google i theo sau để thiết lập ứng dụng của tôi (https://developers.google.com/+/web/signin/javascript-flow) ngay cả khi nó không đề cập đến nó, nó sử dụng tham số "lực". Hiện tại, có vẻ như giải pháp duy nhất nếu bạn muốn sử dụng luồng javascript (có nghĩa là nếu bạn cần nút đăng nhập kiểu cá nhân)

1

Đó là kế hoạch cố ý cho cấu hình cấp trang! Nó hiện diện trong trang khiến cho cuộc gọi lại kích hoạt khi Javascript tải xong. Những gì bạn nên làm là chuẩn bị cho điều đó trong mã của bạn.

Không hiển thị nút đăng nhập cho đến khi bạn nhận được cuộc gọi lại - nếu authResult['status']['signed_in'] == true, sau đó coi người dùng là đã đăng nhập (thiết lập phiên, v.v. bất kỳ điều gì bạn thường làm). Nếu nó sai, sau đó hiển thị nút.

function signinCallback(authResult) { 
    if (authResult['status']['signed_in']) { 
    document.getElementById('signinButton').setAttribute('style', 'display: none'); 
    // Do sign in stuff here! 
    } else { 
    document.getElementById('signinButton').setAttribute('style', 'display: block'); 
    } 
} 

Tôi sẽ tránh sử dụng lực lượng nhắc nhở nếu bạn có thể!

+0

Làm cách nào để ẩn nút trợ giúp nếu người dùng phải nhấp vào nút đó để kích hoạt gọi lại? Ẩn nút không khắc phục được vấn đề gọi lại kép. – CRONUS

+0

Đối với phương thức javascript, họ không phải bấm vào nó để kích hoạt một cuộc gọi lại - nó sẽ kích hoạt ngay sau khi nó được thêm vào DOM. Nếu sử dụng cấu hình cấp trang, cấu hình sẽ kích hoạt ngay sau khi tải trang hoàn tất. Vì vậy, lưu lượng sẽ là: tải trang, gọi lại bị sa thải, nếu không được đăng nhập vào nút hiển thị. –

+0

Có lẽ tôi không hiểu điều gì đó ở đó - [JS workflow] (http://developers.google.com/+/web/signin/javascript-flow). Trích dẫn: _You chỉ nên sử dụng sự kiện do người dùng khởi tạo để kích hoạt phương pháp này, chẳng hạn như lần nhấp, để trình chặn cửa sổ bật lên không ngăn hộp thoại ủy quyền mở. Cũng trong ví dụ _onload_ chỉ gọi 'render()', chỉ thêm eventListener vào nút. Gọi lại không được gọi khi tải trang. – CRONUS

0

cuối cùng tôi đã giải quyết bằng cách giải quyết; tôi không biết nếu điều này là đúng cách để tiếp cận hoặc i am chỉ cần gian lận nhưng tôi làm theo cách này:

trước hết là một số kịch bản trong trang (tôi đang sử dụng bootstrap + jquery)

function render() { 
    //I am not using it but kept anyway 

} 
var i; 
// Function called from a onClick on a link or button (the 'sign in with g+' button) 
function gp_login() { 
    i=0; 
    $('#alertbox').remove(); 
    var additionalParams = { 
    'callback': signinCallback, 
    /*'approvalprompt': 'force' finally removed*/ 
    }; 
    $('#gp-login').button('loading'); 
    gapi.auth.signIn(additionalParams); 
} 

function signinCallback(authResult) { //my callback function 
     var email=''; 
     var given_name=''; 
     if (authResult['status']['signed_in']) { //get some user info 
      gapi.client.load('oauth2', 'v2', function() { 
       gapi.client.oauth2.userinfo.get().execute(function(resp){ 
        email = resp.email; //get user email 
        given_name = resp.given_name; //get user email 
        family_name=resp.family_name; 
        id=resp.id; 
        if (i<2) { //execute the doLogin just one time (my cheat) 
         doLogin(email,given_name,family_name,id); //dologin does my logic with an ajax call to signup/register user to my site 
        } 
        i=2; 
       }); 
      }); 
     } else { 
     // Update the app to reflect a signed out user 
     } 

} 

approch này có phần doLogin gọi là chỉ một lần, nhưng gọi lại được gọi hai lần (gapi.client.oauth2.userinfo.get() chức năng này được gọi hai lần); với một chút tinh chỉnh hơn với kiểm tra if/var tôi nghĩ là có thể gọi mọi thứ một lần. Bằng cách này nếu người dùng đã được cấp quyền xác thực, nó sẽ tự động được ký.

Tôi nhận thấy rằng đôi khi google có một lớp cửa sổ bật lên trên dưới cùng của lớp cho thấy một "chào đón trở lại thông báo", nhưng tôi không hiểu khi nó xuất hiện hoặc nếu tôi phải gọi nó bằng tay

+0

Tôi đang xử lý cùng một vấn đề và tôi đã kết thúc việc triển khai một 'sửa lỗi' tương tự nhưng với biến số đúng/sai. – Francisc0

8

Tôi đối mặt với vấn đề tương tự ở đây, nhưng tôi đang gọi gapi.auth.signIn() thông qua trình xử lý nhấn nút. Cuộc gọi lại vẫn được gọi hai lần. Một điều tôi nhận thấy giữa hai đối tượng authResult là authResult.status.method là 'AUTO' trong lần gọi đầu tiên (trước khi cửa sổ popup xuất hiện) và là 'PROMPT' trong cuộc gọi thứ hai sau khi cửa sổ tự động bị loại bỏ do trước đó ủy quyền.

Giải pháp tôi đang khám phá bây giờ là bỏ qua cá thể AUTO và chỉ xử lý cá thể PROMPT của cuộc gọi lại. Bạn không chắc chắn cách thức này sẽ hoạt động khi tôi thu hồi quyền trong Google do thiếu chi tiết trong tài liệu về đối tượng 'trạng thái'.

+0

Cách này hoạt động cho bạn? Tôi đang nghĩ đến việc làm như vậy. – Dale

1

Giống như câu trả lời của Drew Taylor, để tránh gọi lại đôi với dấu javascript tinh khiết trong dung dịch, bạn có thể check the user's session state:

if (authResult["status"]["method"] == "PROMPT") {...} 

Tôi nghĩ rằng khi gọi lại với phương pháp AUTO là bắn bằng thanh hoan nghênh đáy xuất hiện trong lần đăng nhập đầu tiên.

Các vấn đề liên quan