Asp.net mvc 4 MVC4和x27;s DotNetOpenAuth TwitterClient示例不尊重以前的登录

Asp.net mvc 4 MVC4和x27;s DotNetOpenAuth TwitterClient示例不尊重以前的登录,asp.net-mvc-4,twitter-oauth,dotnetopenauth,Asp.net Mvc 4,Twitter Oauth,Dotnetopenauth,如果我使用Internet应用程序模板创建ASP.NET MVC 4 Web应用程序,它将预安装使用一系列OAuth和OpenID提供程序实现身份验证所需的所有组件和配置。只需将我的Twitter用户密钥和密码添加到AuthConfig.cs即可激活通过Twitter的身份验证 然而,它似乎并不像我预期的那样有效 如果我尝试使用Twitter进行身份验证,无论我是否已登录Twitter,它都会显示一个Twitter登录页面。它还将我从Twitter注销,这样我就不得不在下次访问Twitter时重

如果我使用
Internet应用程序
模板创建ASP.NET MVC 4 Web应用程序,它将预安装使用一系列OAuth和OpenID提供程序实现身份验证所需的所有组件和配置。只需将我的Twitter用户密钥和密码添加到
AuthConfig.cs
即可激活通过Twitter的身份验证

然而,它似乎并不像我预期的那样有效

如果我尝试使用Twitter进行身份验证,无论我是否已登录Twitter,它都会显示一个Twitter登录页面。它还将我从Twitter注销,这样我就不得不在下次访问Twitter时重新进行身份验证

这是一个bug,还是需要一些额外的配置来将其转换为更常见的无缝工作流程(对于其他提供商,如谷歌,该工作流程正常工作)

提前谢谢


蒂姆

如果其他人遇到这个问题,我将在这里介绍我的发现(以及一个相当丑陋的解决方法)

使用Fiddler检查
DotNetOpenAuth
和Twitter之间的HTTP流量,很明显身份验证请求包含
force\u login=false
querystring参数,这表明DNOA工作正常。但是,如果我使用Fiddler的脚本功能来修改出站请求并删除
force_login
参数,那么一切都会正常工作。我猜想Twitter的实现在这里是错误的,因为它将任何
force\u login
参数的存在视为等同于
force\u login=true

由于我认为不可能让Twitter修改其API的行为,因此我已经调查了是否有更易访问的解决方案

查看DNOA代码,我看到
force\u login=false
参数通过
DotNetOpenAuthWebConsumer.RequestAuthentication()
方法无条件地添加到HTTP请求中(并在需要时修改为
true

因此,理想的解决方案是DNOA对其身份验证请求参数提供更细粒度的控制,
TwitterClient
明确删除
force\u login=false
参数。不幸的是,当前的DNOA代码库并不直接支持这一点,但是通过创建两个自定义类可以实现相同的效果

第一个是
IOAuthWebWorker
的自定义实现,它是原始
DotNetOpenAuthWebConsumer
类的直接副本,只有一行更改将重定向参数字典初始化为空字典:

using System;
using System.Collections.Generic;
using System.Net;
using DotNetOpenAuth.AspNet.Clients;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;

namespace CustomDotNetOpenAuth
{
    public class CustomDotNetOpenAuthWebConsumer : IOAuthWebWorker, IDisposable
    {
        private readonly WebConsumer _webConsumer;

        public CustomDotNetOpenAuthWebConsumer(ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager)
        {
            if (serviceDescription == null) throw new ArgumentNullException("serviceDescription");
            if (tokenManager == null) throw new ArgumentNullException("tokenManager");

            _webConsumer = new WebConsumer(serviceDescription, tokenManager);
        }

        public HttpWebRequest PrepareAuthorizedRequest(MessageReceivingEndpoint profileEndpoint, string accessToken)
        {
            return _webConsumer.PrepareAuthorizedRequest(profileEndpoint, accessToken);
        }

        public AuthorizedTokenResponse ProcessUserAuthorization()
        {
            return _webConsumer.ProcessUserAuthorization();
        }

        public void RequestAuthentication(Uri callback)
        {
            var redirectParameters = new Dictionary<string, string>();
            var request = _webConsumer.PrepareRequestUserAuthorization(callback, null, redirectParameters);

            _webConsumer.Channel.PrepareResponse(request).Send();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _webConsumer.Dispose();
            }
        }
    }
}
创建了这两个自定义类之后,实现只需要在MVC4
AuthConfig.cs
文件中注册新的
CustomTwitterClient
类的实例:

OAuthWebSecurity.RegisterClient(new CustomTwitterClient("myTwitterApiKey", "myTwitterApiSecret"));
OAuthWebSecurity.RegisterClient(new CustomTwitterClient("myTwitterApiKey", "myTwitterApiSecret"));