10

我在尝试使用 MyOpenID 和 Yahoo 进行身份验证时收到“消息签名不正确”异常。

我几乎使用了 DotNetOpenAuth 3.4.2 附带的 ASP.NET MVC 示例代码

public ActionResult Authenticate(string openid)
{
    var openIdRelyingParty = new OpenIdRelyingParty();
    var authenticationResponse = openIdRelyingParty.GetResponse();

    if (authenticationResponse == null)
    {
        // Stage 2: User submitting identifier
        Identifier identifier;

        if (Identifier.TryParse(openid, out identifier))
        {
            var realm = new Realm(Request.Url.Root() + "openid");
            var authenticationRequest = openIdRelyingParty.CreateRequest(openid, realm);
            authenticationRequest.RedirectToProvider();
        }
        else
        {
            return RedirectToAction("login", "home");
        }
    }
    else
    {
        // Stage 3: OpenID provider sending assertion response
        switch (authenticationResponse.Status)
        {
            case AuthenticationStatus.Authenticated:
            {
                // TODO
            }
            case AuthenticationStatus.Failed:
            {
                throw authenticationResponse.Exception;
            }
        }
    }

    return new EmptyResult();
}

与 Google、AOL 和其他公司合作良好。但是,Yahoo 和 MyOpenID 属于 AuthenticationStatus.Failed 情况,但有以下例外:

DotNetOpenAuth.Messaging.Bindings.InvalidSignatureException: Message signature was incorrect.
   at DotNetOpenAuth.OpenId.ChannelElements.SigningBindingElement.ProcessIncomingMessage(IProtocolMessage message) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\OpenId\ChannelElements\SigningBindingElement.cs:line 139
   at DotNetOpenAuth.Messaging.Channel.ProcessIncomingMessage(IProtocolMessage message) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\Messaging\Channel.cs:line 992
   at DotNetOpenAuth.OpenId.ChannelElements.OpenIdChannel.ProcessIncomingMessage(IProtocolMessage message) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\OpenId\ChannelElements\OpenIdChannel.cs:line 172
   at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestInfo httpRequest) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\Messaging\Channel.cs:line 386
   at DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty.GetResponse(HttpRequestInfo httpRequestInfo) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\OpenId\RelyingParty\OpenIdRelyingParty.cs:line 540

似乎其他人也有同样的问题:http ://trac.dotnetopenauth.net:8000/ticket/172

有人有解决方法吗?

4

3 回答 3

6

原来这是在网络农场环境中使用 DotNetOpenAuth 的问题。

创建 OpenIdRelyingParty 时,请确保在构造函数中传递 null。

这会将您的网站置于 OpenID 无状态或“哑”模式。用户登录的速度稍慢(如果您注意到的话),但您不必编写 IRelyingPartyApplicationStore 以允许 DotNetOpenAuth 在您的农场中工作;

var openIdRelyingParty = new OpenIdRelyingParty(null);
于 2010-03-24T19:24:59.600 回答
5

所有这些讨论都围绕以下问题:

依赖方 (RP) 如何确保包含身份验证令牌的请求来自他将用户请求转发到的 OP(OpenId 提供者)?

以下步骤解释了它是如何发生的

  1. 用户请求到达回复方 (RP),在我们的案例中是我们的网站
  2. 应用程序将该用户对应的唯一签名存储在本地签名存储(LSS)中,然后将该签名嵌入到消息中,并将该消息转发给 OpenId Provider(OP)
  3. 用户键入他的凭据,OP 对他的消息进行身份验证,然后将该消息(其中仍嵌入签名)转发回 RP
  4. RP 将嵌入在消息中的签名与 LSS 中的签名进行比较,如果它们匹配 RP,则对用户进行身份验证

如果在消息从 OP 返回之前 LSS 消失(不知何故),则 RP 无法将签名与之进行比较,因此它无法验证用户并抛出错误:消息签名不正确。

LSS 如何消失:

  1. ASP.net 刷新应用程序池
  2. IIS 重新启动
  3. 在网络农场中,消息由托管在不同服务器上的应用程序提供服务

这个问题的两个解决方案:

  1. RP 在哑模式下运行

    一种。它不在本地存储和签名,因此不使用签名比较来确保消息来自他将用户转发到以进行身份​​验证的 OP

    湾。相反,一旦 RP 从 OP 接收到身份验证消息,它就会将消息发送回 OP 并要求他检查他是否是验证此用户的人并且是消息的发起者。如果 OP 回复是,我是此消息的发起者并且我已创建此消息,则用户已通过 RP 身份验证

  2. 实现您自己的不会消失的持久性存储,无论 ASP.net 对进程做什么,就像使用 SQL 存储会话状态一样。

于 2010-09-30T09:28:35.623 回答
4

我们通过实现IRelyingPartyApplicationStoreIOpenIdApplicationStore在较新版本的 DotNetOpenAuth 中)并将存储类名称添加到 .config 来解决此问题

<dotNetOpenAuth>
  <openid ...>
    <relyingParty>
      ...
      <store type="some.name.space.MyRelyingPartyApplicationStore, some.assembly"/>
    </relyingParty>
  </openid>
  ...
</dotNetOpenAuth>

该接口是其他两个接口的组合,共有五个成员。

/// <summary>
/// A hybrid of the store interfaces that an OpenID Provider must implement, and
/// an OpenID Relying Party may implement to operate in stateful (smart) mode.
/// </summary>
public interface IOpenIdApplicationStore : ICryptoKeyStore, INonceStore
{
}

我们使用哑模式作为快速修复来启动运行,但最终您可能会想要这样的东西。

于 2010-03-25T07:26:15.997 回答