【问题标题】:Dropnet authentication behaviour on Windows Phone 7.1 and 8.0Windows Phone 7.1 和 8.0 上的 Dropnet 身份验证行为
【发布时间】:2014-08-03 21:29:01
【问题描述】:

我有一对使用 Dropnet 进行 Dropbox 集成的 Windows Phone 应用程序。一种是在 Visual Studio Express 2012 中针对 7.1 开发的,另一种是在 Visual Studio 2013 中针对 8.0 开发的。

两者都通过 NuGet 使用 Dropnet 1.9.6 和 RestSharp 104.4.0。

7.1 项目使用以下静态类与 DropNet 身份验证(和文件操作,但为了清楚起见我已将它们排除在外)进行交互。

public static class DropboxStorage
{
    const string UserToken = "UserToken";
    const string UserSecret = "UserSecret";

    private static DropNetClient _Dropbox;
    public static DropNetClient Dropbox
    {
        get
        {
            if (_Dropbox == null)
            {
                _Dropbox = new DropNetClient(AppKey, AppSecret);
                if (IsAuthenticated)
                {
                    _Dropbox.UserLogin = new UserLogin
                    {
                        Token = (string)IsolatedStorageSettings.ApplicationSettings[UserToken],
                        Secret = (string)IsolatedStorageSettings.ApplicationSettings[UserSecret]
                    };
                }
                _Dropbox.UseSandbox = true;
            }
            return _Dropbox;
        }
    }

    public static bool IsAuthenticated
    {
        get
        {
            return IsolatedStorageSettings.ApplicationSettings.Contains(UserToken) &&
                IsolatedStorageSettings.ApplicationSettings.Contains(UserSecret);
        }
    }

    public static void StartAuthentication(Action<Uri> success, Action<Exception> failure)
    {
        Dropbox.GetTokenAsync(userLogin =>
        {
            var url = Dropbox.BuildAuthorizeUrl(userLogin);
            if (success != null) success(new Uri(url, UriKind.RelativeOrAbsolute));
        }, error =>
        {
            if (failure != null) failure(error);
        });
    }

    public static void CheckAuthentication(Uri uri, Action success, Action<Exception> failure)
    {
        if (uri.LocalPath == "/1/oauth/authorize_submit")
        {
            Dropbox.GetAccessTokenAsync((accessToken) =>
            {
                IsolatedStorageSettings.ApplicationSettings[UserToken] = accessToken.Token;
                IsolatedStorageSettings.ApplicationSettings[UserSecret] = accessToken.Secret;
                IsolatedStorageSettings.ApplicationSettings.Save();
                if (success != null) success();
            },
            (error) =>
            {
                if (failure != null) failure(error);
            });
        }
    }

然后通过带有 WebBrowser 控件的页面访问它。

XAML

<phone:WebBrowser x:Name="Browser"
                              IsScriptEnabled="True"
                              Navigated="Browser_Navigated"/>

C#

public partial class DropboxPage : PhoneApplicationPage
{
    public DropboxPage()
    {
        InitializeComponent();

         DropboxStorage.StartAuthentication(
                uri => Browser.Navigate(uri),
                ex => ShowException(ex));
     }

    public void Browser_Navigated(object sender, NavigationEventArgs e)
    {
        Debug.WriteLine(e.Uri.OriginalString);
        DropboxStorage.CheckAuthentication(
            e.Uri,
            () => NavigationService.GoBack(),
            ex => ShowException(ex));
    }

    private void ShowException(Exception e)
    {
        MessageBox.Show(e.Message);
        NavigationService.GoBack();
    }
}

显示 Dropbox 身份验证网页

  • 登录
  • 允许应用访问
  • 成功,应用已连接

当 Dropbox url 包含 /1/oauth/authorize_submit 时,代码确定身份验证成功。

这一切都很完美,但是 8.0 项目的行为有点不同。

第一个区别是BuildAuthorizeUrl调用返回的url。

  • 7.1https://www.dropbox.com/1/oauth/authorize?oauth_token=&lt;token&gt;
  • 8.0 https://api.dropbox.com/1/oauth/authorize?oauth_token=&lt;token&gt;

第二个区别是,一旦应用程序连接,Dropbox url 不会从 /authorize?oauth_token= 更改为 /authorize_submit,因此永远不会调用 GetAccessTokenAsync,并且不会存储用户令牌和用户密码。

迄今为止,我的调查提出了几种不理想的解决方法

  1. GetAccessTokenAsync 调用中删除 url 验证 并吃掉由此产生的 DropboxExceptions
  2. 为初始的BuildAuthorizeUrl 调用添加回调网址。

我目前正在做 1. 只是为了让事情正常运行,但显然这不是一个长期的解决方案。我宁愿避免使用回调 url,因为这对于移动应用程序来说似乎过于复杂。

我追求的是一种让 8.0 项目的行为方式与 7.1 项目相同的方法。我查看了 Dropnet 源代码,其中包含 https://api.dropbox.com 作为它的基本 url,所以我更不清楚 7.1 代码是如何工作的。

【问题讨论】:

    标签: c# windows-phone-7 windows-phone-8 dropnet


    【解决方案1】:

    行为差异是由 8.0 项目使用 System.Windows.Interactivity 将 Navigated 事件转换为对 ViewModel 上的 Command 的调用引起的。这似乎会阻止网站和 WebBrowser 控件正确交互并重定向到https://www.dropbox.com


    当前

    XAML

    <phone:WebBrowser x:Name="Browser"
                      IsScriptEnabled="True"
                      Visibility="{Binding IsAuthenticated, Converter={StaticResource BoolToInvisibilityConverter}}"
                      Source="{Binding AuthenticateUri}">               
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Navigated" >
                <i:InvokeCommandAction Command="{Binding BrowserNavigated}" 
                                        CommandParameter="{Binding Source, ElementName=Browser}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </phone:WebBrowser>
    

    C#

    BrowserNavigated = new RelayCommand<Uri>(u =>
                    {                   
                        RemoteStorage.CheckAuthentication(u, () => IsAuthenticated = true, ex => ShowException(ex));
                    });
    

    已更正

    XAML

            <phone:WebBrowser x:Name="Browser"
                              IsScriptEnabled="True"
                              Visibility="{Binding IsAuthenticated, Converter={StaticResource BoolToInvisibilityConverter}}"
                              Source="{Binding AuthenticateUri}"
                              Navigated="Browser_Navigated"/>
    

    C#

        private void Browser_Navigated(object sender, NavigationEventArgs e)
        {
            ViewModel.BrowserNavigated.Execute(e.Uri);
        }
    

    在这两种情况下,绑定到 WebBrowser Source 的视图模型的 AuthenticateUri 属性由 DropboxStorage 类中的 StartAuthentication 方法设置。

    添加事件处理程序后,8.0 项目按预期工作。

    【讨论】:

      【解决方案2】:

      不久前我也开始看到这个问题。直到那时,我的应用程序在 WP8 上运行良好。我不记得所有细节,但我查看了我的签入以修复它,我认为第一个 url 的额外页面加载开始发生。 Dropbox 也没有关于更改的警告。

      为了解决这个问题,我等待某个 url 出现在 LoadCompleted 事件中。您使用Navigated 事件,我认为它也应该起作用。

      我会像这样修改你的事件处理程序:

      public void Browser_Navigated(object sender, NavigationEventArgs e)
      {
          if (e.Uri.AbsolutePath == "/1/oauth/authorize_submit")
          {
              DropboxStorage.CheckAuthentication(
                  e.Uri,
                  () => NavigationService.GoBack(),
                  ex => ShowException(ex));
          }
      }
      

      【讨论】:

      • 谢谢,但是如果您查看 CheckAuthentication 的代码,我已经在 uri LocalPath 中寻找 /1/oauth/authorize_submit。但是,您确实为我指明了正确的方向,因为我的 8.0 项目没有 Browser_Navigated 事件处理程序,而是使用 System.Windows.Interactivity 将 Navigated 事件转换为 Command 调用。显然这样做会阻止 Dropbox 网站重定向正常工作。我已经切换回使用事件处理程序,它现在可以正常工作了。
      • 我也隐约记得在 7.1 项目中遇到过类似的问题(很久以前,所以细节模糊)。我通过将 RestSharp 从 Dropnet 安装的 104.1 更新到 104.4 来解决这个问题。
      猜你喜欢
      • 1970-01-01
      • 2015-08-01
      • 2014-08-30
      • 1970-01-01
      • 1970-01-01
      • 2013-10-24
      • 2023-03-28
      • 1970-01-01
      • 2015-03-17
      相关资源
      最近更新 更多