【问题标题】:Friendly name from Google using OpenID?使用 OpenID 的 Google 友好名称?
【发布时间】:2009-08-31 00:14:38
【问题描述】:

当我使用 Google OpenID 提供商打乒乓球时,我无法获得友好的名称/昵称/用户名(无论您想怎么称呼它)。

我得到了一些看起来像下面这样的残暴的东西:

www.google.com/accounts/o8/id?id=AItOawmtAnQvSXGhRTkAHZWyxi4L4EKa7xoTT1dk  

而不是像这样的好东西

JohnDoe

以友好的方式从 Google 获取用户名的协议是什么,比如 myopenid 呢?

**我正在使用 DotNetOpenAuth*

【问题讨论】:

    标签: openid dotnetopenauth


    【解决方案1】:

    你不能。 OP 发布的标识符完全取决于 OP。 RP真的没有发言权。现在,一些 OP 支持在登录时提供属性,例如昵称、电子邮件地址等。Google 对这些属性的支持非常有限,仅提供电子邮件地址。

    Google 选择不发布用户可识别的标识符,因为这存在信息泄露风险。雅虎通过为用户提供用户可以选择的人性化和非人性化标识符来走这两条路。 MyOpenID 和其他 OP 通常只使用用户在 OP 上注册时选择的用户友好标识符。

    您可能希望在您的 RP 上对 Google 进行特殊处理,以便在用户登录时选择一个更友好的字符串来显示给用户,或者由于 Google 不是唯一这样做的,请编写代码来确定何时标识符不可读,并显示对用户更友好的内容,以便他们知道自己已登录(可能是他们的电子邮件地址或他们在您的网站上选择的昵称)。

    注意:如果您选择显示比 Google 提供的更友好的标识符,您仍必须使用 Google 的官方声明标识符作为官方用户名传递给FormsAuthentication.RedirectFromLogin 的用户并在数据库中查找用户名。您放在一起的任何其他内容通常都会带来安全风险。

    【讨论】:

    • 感谢您解决这个问题。我想使用默认的友好标识符作为用户的电子邮件可以工作。您是否碰巧知道哪些其他服务在友好名称方面表现不佳?
    • Yahoo 是我所知道的唯一一个,它有时只有这种行为。
    • 安德鲁,我设法深入了解了您的博客文章,并找到了关于雅虎的文章。我必须再读一遍才能完全理解它——但在我不知情的试验中,我什至无法从雅虎那里得到一个电子邮件地址,当我使用雅虎登录进行 stackoverflow 时,这让我感到困惑——而且我的信息清楚地转移了.. .
    【解决方案2】:

    基于 Roy 的回答,我尝试使用 DotNetOpenAuth 提出相同的请求,并且效果很好。 请求:

    var req = openid.CreateRequest("https://www.google.com/accounts/o8/id");
    var fetch = new FetchRequest();
    fetch.Attributes.Add(new AttributeRequest(WellKnownAttributes.Contact.Email,true));
    fetch.Attributes.Add(new AttributeRequest(WellKnownAttributes.Name.First,true));
    fetch.Attributes.Add(new AttributeRequest(WellKnownAttributes.Name.Last,true));
    
    req.AddExtension(fetch);
    

    注意:确保 AttributeRequest 构造函数的第二个参数设置为 true。

    响应部分是直截了当的。

    var openid = new OpenIdRelyingParty();
    var response = openid.GetResponse();
    var fetch = response.GetExtension<FetchResponse>();
    if (fetch != null) {
    IList<string> emailAddresses =fetch.Attributes[WellKnownAttributes.Contact.Email].Values;
    IList<string> firstNames = fetch.Attributes[WellKnownAttributes.Name.First].Values;
    IList<string> lastName = fetch.Attributes[WellKnownAttributes.Name.Last].Values;
    }
    

    【讨论】:

    • 根据您使用它的方式(我正在使用 OWIN),您可能在项目中安装的一组东西中没有 WellKnownAttributes,并且您可能不想添加 DotNetOpenAuth 只是为了这。以下是其 WellKnownAttributes(以及其他 OpenId 库中的其他位置)中的 OpenId 字符串:名字:“given_name”,姓氏:“family_name”,中间名:“middle_name”,昵称:“nickname”
    【解决方案3】:

    截至 2012 年,Google OpenID endpoint 似乎支持通过属性交换协议检索名字和姓氏。下面是一些使用 Pyramid Web 框架和 Janrain 的 python-openid 包的 Python 代码示例。

    from openid.consumer import consumer
    from openid.extensions.ax import AttrInfo, FetchRequest, FetchResponse
    from openid.store.filestore import FileOpenIDStore
    from openid.store.sqlstore import PostgreSQLStore, MySQLStore, SQLiteStore
    
    AX_FIRSTNAME = 'http://axschema.org/namePerson/first'
    AX_LASTNAME = 'http://axschema.org/namePerson/last'
    AX_EMAIL = 'http://axschema.org/contact/email'
    
    @view_config(route_name='openID_start', permission=NO_PERMISSION_REQUIRED)
    def start(request):
        'Start openID authentication process'
        params = request.params
        openIDURL = params.get('openIDURL')
        if not openIDURL:
            return HTTPResponse('Parameter expected: openIDURL')
        openIDConsumer = get_consumer(request)
        try:
            openIDRequest = openIDConsumer.begin(openIDURL)
        except consumer.DiscoveryFailure, error:
            return HTTPResponse('Discovery failed: %s' % escape(error))
        else:
            if not openIDRequest:
                return HTTPResponse('Not an openID provider: %s' % escape(openIDURL))
    
            axRequest = FetchRequest()
            axRequest.add(AttrInfo(AX_FIRSTNAME, required=True))
            axRequest.add(AttrInfo(AX_LASTNAME, required=True))
            axRequest.add(AttrInfo(AX_EMAIL, required=True))
            openIDRequest.addExtension(axRequest)
    
            sourceURL = request.host_url
            targetURL = request.route_url('openID_finish')
            if openIDRequest.shouldSendRedirect():
                return HTTPFound(location=openIDRequest.redirectURL(sourceURL, targetURL))
            return HTTPResponse(openIDRequest.htmlMarkup(sourceURL, targetURL))
    
    @view_config(route_name='openID_finish', permission=NO_PERMISSION_REQUIRED)
    def finish(request):
        'Finish openID authentication process'
        openIDConsumer = get_consumer(request)
        targetURL = request.route_url('openID_finish')
        openIDResponse = openIDConsumer.complete(request.params, targetURL)
        html = openIDResponse.status + '<br>'
        for key, value in openIDResponse.__dict__.iteritems():
            html += '%s: %s<br>' % (escape(key), escape(value))
        html += '<br>'
        if consumer.SUCCESS == openIDResponse.status:
            axResponse = FetchResponse.fromSuccessResponse(openIDResponse)
            html += 'First name: %s<br>' % escape(axResponse.get(AX_FIRSTNAME))
            html += 'Last name: %s<br>' % escape(axResponse.get(AX_LASTNAME))
            html += 'Email: %s<br>' % escape(axResponse.get(AX_EMAIL))
        return HTTPResponse(html)
    
    def get_consumer(request):
        try:
            openIDStore = {
                'sqlite': SQLiteStore,
                'postgresql': PostgreSQLStore,
                'mysql': MySQLStore,
            }[db.bind.name](db.bind.raw_connection())
        except KeyError:
            openIDStore = FileOpenIDStore('data/openIDs')
        try:
            openIDStore.createTables()
        except:
            pass
        return consumer.Consumer(request.session, openIDStore)
    

    【讨论】:

    • 像炸弹一样工作。 /namePerson/first 和 /namePerson/last
    猜你喜欢
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    相关资源
    最近更新 更多