代码之家  ›  专栏  ›  技术社区  ›  Shawn Miller

DotNetOpenAuth:消息签名不正确

  •  10
  • Shawn Miller  · 技术社区  · 15 年前

    我在尝试对myopenid和yahoo进行身份验证时收到一个“消息签名不正确”异常。

    我使用的几乎是DotNetOpenAuth3.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();
    }
    

    与谷歌、美国在线和其他公司合作良好。但是,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

    有人有解决办法吗?

    3 回复  |  直到 12 年前
        1
  •  6
  •   Shawn Miller    15 年前

    结果发现,这是在Web场环境中使用DotNetOpenAuth时出现的问题。

    创建OpenIDrelyingParty时,请确保在构造函数中传递空值。

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

    var openIdRelyingParty = new OpenIdRelyingParty(null);
    
        2
  •  5
  •   Drew Noakes    12 年前

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

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

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

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

    如果LSS在消息从OP返回之前消失(不知何故),RP就没有什么可与之比较的签名,因此它无法对用户进行身份验证并引发错误:消息签名不正确。

    LSS如何消失:

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

    此问题的两种解决方案:

    1. rp以哑模式运行_s

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

      B. 相反,一旦RP收到来自OP的身份验证消息,它会将消息发送回OP,并要求他检查他是否是对该用户进行身份验证的人,并且是消息的发起人。如果OP回复“是”,我是此邮件的创建者,并且我已经创建了此邮件,那么用户将通过RP进行身份验证。

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

        3
  •  4
  •   Drew Noakes    12 年前

    我们通过实施 IRelyingPartyApplicationStore ( IOpenIdApplicationStore 在较新版本的dotneopenauth中)并将存储类名添加到.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
    {
    }
    

    我们使用了哑模式作为快速修复来开始跑步,但最终你可能会想要这样的东西。