2010-10-31 35 views
42

Tôi đã thực hiện rất nhiều nghiên cứu về chủ đề này và đã tự mình triển khai nhiều giải pháp.Cách tốt nhất để triển khai Đăng nhập một lần với tất cả các nhà cung cấp chính?

Bao gồm OpenID, Facebook Connect (sử dụng API Rest cũ và API đồ thị OAuth 2.0 mới), Đăng nhập bằng twitter (đã được nâng cấp lên OpenID đủ điều kiện hiện tại theo như tôi biết), v.v. ..

Nhưng những gì tôi vẫn còn thiếu là giải pháp hoàn hảo tất cả trong một.

Trong nghiên cứu của tôi, tôi loạng choạng về một số dự án thú vị:

Nhưng tôi không muốn dựa vào một nhà cung cấp bên ngoài và tôi sẽ giống như giải pháp miễn phí, vì vậy tôi không bị giới hạn trong việc triển khai.

Tôi cũng đã thấy các nhà phát triển triển khai một dịch vụ sau một dịch vụ khác theo hướng dẫn của nhà cung cấp và thiết lập mô hình và bảng cơ sở dữ liệu cho mọi thứ.

Tất nhiên điều này sẽ làm việc nhưng nó là một shitload công việc và luôn cần sự phát triển và thay đổi trong ứng dụng của bạn, vv

Những gì tôi đang tìm kiếm là một lớp trừu tượng mà sẽ đưa tất cả các dịch vụ hiện có để một tiêu chuẩn có thể được tích hợp trong trang web của tôi. Khi một dịch vụ mới xuất hiện, tôi chỉ muốn thêm một mô hình thỏa thuận với sự trừu tượng của nhà cung cấp cụ thể đó để tôi có thể tích hợp liền mạch nó vào ứng dụng của tôi.

Hoặc tốt hơn, hãy tìm một giải pháp đã tồn tại mà tôi có thể tải xuống.

Lý tưởng nhất là dịch vụ trừu tượng này sẽ được lưu trữ độc lập từ ứng dụng của tôi để nó có thể được sử dụng cho một số ứng dụng và được nâng cấp độc lập.

Cuối cùng trong số 3 giải pháp ở trên có vẻ đầy hứa hẹn từ khái niệm. Mọi thứ chỉ được chuyển đến OpenID tổng hợp và trang web phải triển khai OpenID.

Sau một thời gian tôi tìm thấy Django socialauth, một hệ thống xác thực dựa trên python cho Webframework Django. Nhưng có vẻ như nó hoạt động như mô tả ở trên và tôi nghĩ rằng đây là cùng một hệ thống đăng nhập mà Stackoverflow sử dụng (hoặc ít nhất một số ngã ba sửa đổi ...).

Tôi đã tải xuống và cố gắng thiết lập và xem liệu nó có thể được thiết lập như một giải pháp độc lập hay không, nhưng tôi cũng không may mắn vì tôi cũng không phải như vậy.

Tôi rất thích một giải pháp dựa trên PHP.

Vì vậy, sau khi văn bản dài câu hỏi của tôi này chính là:

  • Làm thế nào bạn sẽ thực hiện SSO, bất kỳ ý tưởng tốt hơn so với porting tất cả mọi thứ và có OpenID làm cơ sở?
  • Ưu và nhược điểm của điều đó là gì?
  • Bạn có biết bất kỳ giải pháp đã tồn tại nào không? Ưu tiên nguồn mở.

Tôi hy vọng câu hỏi này không quá chủ quan, cảm ơn trước.

Cập nhật: Tôi kết luận rằng xây dựng proxy/trình bao bọc hoặc những gì bạn có thể gọi cho Facebook, để chuyển nó sang OpenID để nó trở thành điểm cuối/nhà cung cấp OpenID sẽ là lựa chọn tốt nhất. Vì vậy, đó chính xác là những gì tôi đã làm.

Vui lòng xem câu trả lời của tôi bên dưới.

Tôi đã thêm tiền thưởng để nhận phản hồi/thảo luận về nó. Maby cách tiếp cận của tôi không phải là quá tốt như tôi hiện đang nghĩ rằng nó được!

+0

tôi đã sửa đổi lớp của mình một chút và sửa một số lỗi! sẽ đặt nó trên github hoặc một cái gì đó khi nó được thực hiện, ủng hộ câu hỏi để có được bản cập nhật. –

+0

Tôi không nghĩ câu hỏi này không đủ xây dựng để đóng. – markus

+1

nevermind @ markus-tharkun, tôi cảm thấy như thực sự giúp đỡ nhau đã trở thành không quan trọng trên SO. nó giống như một chế độ với những định nghĩa riêng của nó về những gì và không tạo ra một câu hỏi hay và mong muốn săn lùng tất cả những người khác và làm nhục người hỏi để anh ta sẽ không bao giờ quay trở lại nữa. –

Trả lời

13

Như tác giả ban đầu của câu trả lời này, tôi muốn lưu ý rằng tôi coi đó là lỗi thời. Vì hầu hết các nhà cung cấp đã quyết định triển khai độc quyền Oauth thay vì Openid. Các dịch vụ Openid mới hơn cũng sẽ có khả năng sử dụng kết nối mở, dựa trên oauth. Có thư viện tốt như ví dụ:

Sau khi thảo luận về câu trả lời đã có sẵn i Tóm lại:

Hầu hết các nhà cung cấp chính là một nhà cung cấp OpenID/endpoint bao gồm Google, Yahoo, AOL.

Một số người trong số họ yêu cầu người dùng chỉ định tên người dùng để xây dựng điểm cuối mở. Một số người trong số họ (những người được đề cập ở trên) có url khám phá, trong đó id người dùng được tự động trả lại để người dùng chỉ phải nhấp vào. (Tôi sẽ rất vui nếu có ai đó có thể giải thích về nền tảng kỹ thuật)

Tuy nhiên, nỗi đau duy nhất trong ass là Facebook, bởi vì họ có kết nối Facebook của họ nơi họ sử dụng phiên bản OAuth được điều chỉnh để xác thực.

Bây giờ những gì tôi đã làm cho dự án của mình là thiết lập nhà cung cấp dịch vụ xác thực người dùng với thông tin đăng nhập của ứng dụng facebook của tôi - để người dùng được kết nối với ứng dụng của tôi - và trả về id người dùng như sau:

http://my-facebook-openid-proxy-subdomain.mydomain.com/?id=facebook-user-id 

Tôi cũng đã định cấu hình nó để tìm nạp địa chỉ email và tên và trả về dưới dạng thuộc tính AX.

Vì vậy, trang web của tôi chỉ cần có để thực hiện id mở cánh và tôi đang tốt đẹp :)

tôi xây dựng nó trên các lớp bạn có thể tìm thấy ở đây: http://gitorious.org/lightopenid

Trong file index.php của tôi tôi chỉ gọi nó như thế này:

<?php 
require 'LightOpenIDProvider.php'; 
require 'FacebookProvider.php'; 
$op = new FacebookProvider; 
$op->appid = 148906418456860; // your facebook app id 
$op->secret = 'mysecret'; // your facebook app secret 
$op->baseurl = 'http://fbopenid.2xfun.com'; // needs to be allowed by facebook 
$op->server(); 
?> 

và mã nguồn của FacebookProvider.php sau:

<?php 
class FacebookProvider extends LightOpenIDProvider 
{ 
    public $appid = ""; 
    public $appsecret = ""; 
    public $baseurl = ""; 

    // i have really no idea what this is for. just copied it from the example. 
    public $select_id = true; 

    function __construct() { 

     $this->baseurl = rtrim($this->baseurl,'/'); // no trailing slash as it will be concatenated with 
                // request uri wich has leading slash 

     parent::__construct(); 

     # If we use select_id, we must disable it for identity pages, 
     # so that an RP can discover it and get proper data (i.e. without select_id) 
     if(isset($_GET['id'])) { 
      // i have really no idea what happens here. works with or without! just copied it from the example. 
      $this->select_id = false; 
     } 
    } 

    function setup($identity, $realm, $assoc_handle, $attributes) 
    { 
     // here we should check the requested attributes and adjust the scope param accordingly 
     // for now i just hardcoded email 
     $attributes = base64_encode(serialize($attributes));  

     $url = "https://graph.facebook.com/oauth/authorize?client_id=".$this->appid."&redirect_uri="; 

     $redirecturl = urlencode($this->baseurl.$_SERVER['REQUEST_URI'].'&attributes='.$attributes); 
     $url .= $redirecturl; 
     $url .= "&display=popup"; 
     $url .= "&scope=email"; 
     header("Location: $url"); 
     exit();   

    } 

    function checkid($realm, &$attributes) 
    { 
     // try authenticating 
     $code = isset($_GET["code"]) ? $_GET["code"] : false; 
     if(!$code) { 
      // user has not authenticated yet, lets return false so setup redirects him to facebook 
      return false; 
     } 

     // we have the code parameter set so it looks like the user authenticated 
     $url = "https://graph.facebook.com/oauth/access_token?client_id=148906418456860&redirect_uri="; 

     $redirecturl = ($this->baseurl.$_SERVER['REQUEST_URI']); 
     $redirecturl = strstr($redirecturl, '&code', true); 
     $redirecturl = urlencode($redirecturl);  
     $url .= $redirecturl; 
     $url .= "&client_secret=".$this->secret; 
     $url .= "&code=".$code; 
     $data = $this->get_data($url); 

     parse_str($data,$data); 

     $token = $data['access_token']; 

     $data = $this->get_data('https://graph.facebook.com/me?access_token='.urlencode($token)); 
     $data = json_decode($data); 

     $id = $data->id; 
     $email = $data->email; 
     $attribute_map = array(
      'namePerson/friendly' => 'name', // we should parse the facebook link to get the nickname 
      'contact/email' => 'email', 
     ); 

     if($id > 0) { 

      $requested_attributes = unserialize(base64_decode($_GET["attributes"])); 

      // lets be nice and return everything we can 
      $requested_attributes = array_merge($requested_attributes['required'],$requested_attributes['optional']); 
      $attributes = array(); 
      foreach($requested_attributes as $requsted_attribute) { 
       if(!isset($data->{$attribute_map[$requsted_attribute]})) { 
        continue; // unknown attribute 
       } 
       $attributes[$requsted_attribute] = $data->{$attribute_map[$requsted_attribute]};  
      } 

      // yeah authenticated! 
      return $this->serverLocation . '?id=' . $id ; 
     } 
     die('login failed'); // die so we dont retry bouncing back to facebook 
     return false; 
    } 
    function get_data($url) { 
     $ch = curl_init(); 
     $timeout = 5; 
     curl_setopt($ch,CURLOPT_URL,$url); 
     curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 
     curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout); 
     $data = curl_exec($ch); 
     curl_close($ch); 
     return $data; 
    }  

} 

Chỉ là phiên bản làm việc đầu tiên (nhanh và bẩn) Một số nội dung động được mã hóa theo nhu cầu của tôi. Nó sẽ hiển thị như thế nào và nó có thể được thực hiện. Tôi hạnh phúc nếu ai đó nhặt và cải thiện nó hoặc tái viết nó hay bất cứ điều gì :)

Vâng tôi xem xét câu hỏi này đã trả lời

nhưng tôi thêm một tiền thưởng chỉ để có được thảo luận. Tôi muốn biết bạn nghĩ gì về giải pháp của tôi.

Tôi sẽ trao phần thưởng cho câu trả lời/nhận xét phù hợp nhất bên cạnh câu trả lời này.

+1

Nó có thể an toàn hơn để lưu trữ appid như một chuỗi: đó là một số nguyên nguy hiểm chất béo lớn '$ op-> appid = '148906418456860'; ' –

+0

true;) phổ biến" sai lầm ".. tuy nhiên tôi có xu hướng ném một" xin vui lòng nâng cấp lên 64 bit "ngoại lệ: P –

+0

tôi nghĩ rằng nó có thể đáng nhắc đến là tại thời điểm câu trả lời này đã được tạo ra baiscally đúng, tuy nhiên quá trình lịch sử muốn nó oauth là người chiến thắng trên openid ... vì vậy nó có lẽ sẽ là tốt hơn để tập trung vào đó. –

5

OpenID sẽ là đặt cược tốt nhất của bạn cho ứng dụng này. Nó được hỗ trợ bởi nhiều nhà cung cấp:

  • Google
  • Yahoo
  • Myopenid
  • AOL

Vấn đề duy nhất là twitter đã không được thực hiện OpenID được nêu ra. Điều này có thể là do họ là một công ty sở hữu dựa trên sở hữu, vì vậy họ muốn có giải pháp riêng của họ.

Để giải quyết giải pháp đó, bạn có thể viết lớp bao bọc để tương thích với OpenID, nhưng cơ hội là ngay cả khi người dùng của bạn không có tài khoản twitter, họ có thể có tài khoản Facebook, Google hoặc Yahoo.

Facebook Hỗ trợ oauth, vì vậy bạn sẽ phải cổng oauth để OpenID

Một số thư viện PHP cho OpenID thể được tìm thấy here.

Bây giờ, một số câu hỏi đã được nêu ra về facebook là một nhà cung cấp oauth.

URL oauth của họ là "https://graph.facebook.com/oauth/authorize"

Nếu bạn vẫn không belive tôi, sau đó bạn có thể nhìn vào this tập tin javascript, nơi tôi đã nhận URL đó. Nếu bạn không tin rằng tập tin javascript, sau đó nhận thấy rằng nó được lưu trữ bởi stackexchange, nhà cung cấp của trang web này. Bây giờ bạn phải tin điều đó.

+0

Maby tôi bỏ qua điều gì đó nhưng khi nói đến Facebook và OpenID, nó trông giống như khả năng duy nhất là liên kết tài khoản OpenId với tài khoản Facebook của bạn. Điều tôi muốn là mọi người có thể xác thực trên trang web của tôi bằng tài khoản facebook của họ. Tôi không tìm thấy bất kỳ tài nguyên nào về điều đó? Maby bạn có thể chỉ cho tôi đi đúng hướng hoặc cung cấp cho tôi một liên kết? –

+0

Facebook là nhà cung cấp OpenID. Tôi đăng một liên kết trong câu trả lời, nếu bạn nhìn vào danh sách các nhà cung cấp, facebook là một liên kết. – xaav

+0

Tôi đã chỉnh sửa câu hỏi để làm rõ hơn về Facebook – xaav

2

Tua đi hai năm và câu trả lời của "OpenID là câu trả lời" dường như nằm ở bên lề bởi một số nhà cung cấp lớn. Hầu hết các trang web tích hợp của bên thứ ba dường như đã chuyển sang một số hương vị của OAuth (thường là OAuth2). Ngoài ra, nếu bạn không nhớ KHÔNG sử dụng OpenID/OAuth, hiện có giải pháp SSO hoàn chỉnh được viết bằng PHP (Tuyên bố từ chối trách nhiệm và tiết lộ đầy đủ: Sản phẩm này được phát triển và duy trì một mình dưới biểu ngữ CubicleSoft):

Single Sign-On Server/Client

Điều không tồn tại khi câu hỏi này ban đầu được hỏi. Nó có một giấy phép tự do (MIT hoặc LGPL) và đáp ứng yêu cầu của bạn là một lớp trừu tượng. Dự án có xu hướng tập trung vào việc đăng nhập doanh nghiệp nhưng cũng có một số đăng nhập phương tiện truyền thông xã hội trong quá trình kết hợp (Google và Facebook). Bạn cũng có thể muốn xem HybridAuth, chỉ tập trung vào đăng nhập phương tiện truyền thông xã hội nhưng có nhiều thư viện hơn là giải pháp dựng sẵn mà bạn có thể ném vào máy chủ và được thực hiện cùng với nó. Vì vậy, có một chút công việc liên quan đến việc thiết lập nó. Nó thực sự phụ thuộc vào những gì bạn đang sau.

Nếu bạn hài lòng với giải pháp OpenID của mình, thì tuyệt vời, nhưng có nhiều tùy chọn hơn hôm nay so với hai năm trước và mọi người vẫn đang tìm chủ đề này.

+0

Cảm ơn bạn đã đăng câu trả lời! Vui lòng đảm bảo đọc kỹ [FAQ on Self-Promotion] (http://stackoverflow.com/faq#promotion). Đặc biệt lưu ý rằng nó là * bắt buộc * mà bạn đăng tuyên bố từ chối trách nhiệm mỗi khi bạn liên kết đến trang web/sản phẩm của mình, * và * rằng lý do chính của bạn để ở đây không được quảng bá (các) sản phẩm/trang web của bạn. –

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