首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenID发现方法- Yadis VS HTML

OpenID发现方法- Yadis VS HTML
EN

Stack Overflow用户
提问于 2010-07-16 02:10:43
回答 1查看 1.6K关注 0票数 6

最近,为了更好地理解openID,我开始编写自己的PHP消费者类。作为指南,我一直在引用LightOpenID类。在大多数情况下,我理解代码和OpenID的工作原理。当查看作者的discover函数时,我感到困惑:

代码语言:javascript
复制
function discover($url)
{
    if(!$url) throw new ErrorException('No identity supplied.');
    # We save the original url in case of Yadis discovery failure.
    # It can happen when we'll be lead to an XRDS document
    # which does not have any OpenID2 services.
    $originalUrl = $url;

    # A flag to disable yadis discovery in case of failure in headers.
    $yadis = true;

    # We'll jump a maximum of 5 times, to avoid endless redirections.
    for($i = 0; $i < 5; $i ++) {
        if($yadis) {
            $headers = explode("\n",$this->request($url, 'HEAD'));

            $next = false;
            foreach($headers as $header) {
                if(preg_match('#X-XRDS-Location\s*:\s*(.*)#', $header, $m)) {
                    $url = $this->build_url(parse_url($url), parse_url(trim($m[1])));
                    $next = true;
                }

                if(preg_match('#Content-Type\s*:\s*application/xrds\+xml#i', $header)) {
                    # Found an XRDS document, now let's find the server, and optionally delegate.
                    $content = $this->request($url, 'GET');

                    # OpenID 2
                    # We ignore it for MyOpenID, as it breaks sreg if using OpenID 2.0
                    $ns = preg_quote('http://specs.openid.net/auth/2.0/');
                    if (preg_match('#<Service.*?>(.*)<Type>\s*'.$ns.'(.*?)\s*</Type>(.*)</Service>#s', $content, $m)
                        && !preg_match('/myopenid\.com/i', $this->identity)) {
                        $content = $m[1] . $m[3];
                        if($m[2] == 'server') $this->identifier_select = true;

                        $content = preg_match('#<URI>(.*)</URI>#', $content, $server);
                        $content = preg_match('#<LocalID>(.*)</LocalID>#', $content, $delegate);
                        if(empty($server)) {
                            return false;
                        }
                        # Does the server advertise support for either AX or SREG?
                        $this->ax   = preg_match('#<Type>http://openid.net/srv/ax/1.0</Type>#', $content);
                        $this->sreg = preg_match('#<Type>http://openid.net/sreg/1.0</Type>#', $content);

                        $server = $server[1];
                        if(isset($delegate[1])) $this->identity = $delegate[1];
                        $this->version = 2;

                        $this->server = $server;
                        return $server;
                    }

                    # OpenID 1.1
                    $ns = preg_quote('http://openid.net/signon/1.1');
                    if(preg_match('#<Service.*?>(.*)<Type>\s*'.$ns.'\s*</Type>(.*)</Service>#s', $content, $m)) {
                        $content = $m[1] . $m[2];

                        $content = preg_match('#<URI>(.*)</URI>#', $content, $server);
                        $content = preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $content, $delegate);
                        if(empty($server)) {
                            return false;
                        }
                        # AX can be used only with OpenID 2.0, so checking only SREG
                        $this->sreg = preg_match('#<Type>http://openid.net/sreg/1.0</Type>#', $content);

                        $server = $server[1];
                        if(isset($delegate[1])) $this->identity = $delegate[1];
                        $this->version = 1;

                        $this->server = $server;
                        return $server;
                    }

                    $next = true;
                    $yadis = false;
                    $url = $originalUrl;
                    $content = null;
                    break;
                }
            }
            if($next) continue;

            # There are no relevant information in headers, so we search the body.
            $content = $this->request($url, 'GET');
            if($location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'value')) {
                $url = $this->build_url(parse_url($url), parse_url($location));
                continue;
            }
        }

        if(!$content) $content = $this->request($url, 'GET');

        # At this point, the YADIS Discovery has failed, so we'll switch
        # to openid2 HTML discovery, then fallback to openid 1.1 discovery.
        $server   = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href');
        $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href');
        $this->version = 2;

        # Another hack for myopenid.com...
        if(preg_match('/myopenid\.com/i', $server)) {
            $server = null;
        }

        if(!$server) {
            # The same with openid 1.1
            $server   = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href');
            $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href');
            $this->version = 1;
        }

        if($server) {
            # We found an OpenID2 OP Endpoint
            if($delegate) {
                # We have also found an OP-Local ID.
                $this->identity = $delegate;
            }
            $this->server = $server;
            return $server;
        }

        throw new ErrorException('No servers found!');
    }
    throw new ErrorException('Endless redirection!');
}


  [1]: http://gitorious.org/lightopenid

好吧,这就是我所理解的逻辑(基本上):

  1. 检查$url是否向您发送了一个有效的XRDS文件,然后解析该文件以确定OpenID提供者的端点。
    • 据我所知,这被称为Yadis身份验证方法。

  1. 如果没有找到XRDS文件,请检查响应的主体,以查找包含端点url的HTML标记。

什么。这个。见鬼。

我是说真的吗?本质上,屏幕擦除响应,并希望找到一个具有适当属性值的链接?

现在,别误会我的意思,这门课很有魅力,很棒。我只是没有摸索用于发现端点的两个单独的方法: XRDS (yadis)和HTML。

我的问题

  1. 这是发现过程中唯一使用的两种方法吗?
  2. 一个只在OpenID的1.1版本中使用,另一个在版本2中使用吗?
  3. 支持这两种方法至关重要吗?
  4. 我在上面遇到的HTML方法的站点是Yahoo。他们疯了吗?

再次感谢各位时间的到来。如果我听起来有点不知所措的话,我很抱歉,但是当我开始理解正在采取什么措施来找到endPoint时,我真的对这个方法感到震惊。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-07-17 10:45:44

规格说明是你的朋友。

但回答你的问题:

  1. 是。这是OpenID规范定义的唯一两种方法(至少对于URL来说是这样-- XRIs有第三种方法)。
  2. 不,这两种方法都可以与协议的两种版本一起使用。仔细阅读该函数,您将看到它支持这两个版本的两种方法。
  3. 如果您希望您的库与每个提供者和用户一起工作,那么最好这样做。一些用户将HTML标记粘贴到他们的站点中,这样他们的站点的url就可以作为openid使用。
  4. 有些提供者甚至同时使用这两种方法,以保证与未实现YADIS发现的消费者的兼容性(这不是YADIS 1.1的一部分,但可以与其一起使用)。所以这是有道理的。

是的,HTML发现是关于在响应体中搜索<link>。这就是为什么它被称为HTML发现。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3261459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档