17

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

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

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

而不是像这样的好东西

JohnDoe

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

**我正在使用 DotNetOpenAuth*

4

3 回答 3

13

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

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

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

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

于 2009-08-31T00:45:20.007 回答
10

根据罗伊的回答,我尝试使用相同的请求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;
}
于 2012-04-27T16:21:23.037 回答
6

截至 2012 年, Google OpenID 端点似乎支持通过属性交换协议检索名字和姓氏。这是一些使用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)
于 2012-02-02T18:42:13.010 回答