我有一对使用 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.1
https://www.dropbox.com/1/oauth/authorize?oauth_token=<token>
- 8.0
https://api.dropbox.com/1/oauth/authorize?oauth_token=<token>
/authorize?oauth_token=
第二个区别是,/authorize_submit
一旦应用程序连接,Dropbox url 就不会改变,因此GetAccessTokenAsync
永远不会被调用,并且不会存储用户令牌和用户密码。
迄今为止,我的调查提出了几种不理想的解决方法
- 从
GetAccessTokenAsync
调用周围删除 url 验证并吃掉生成的 DropboxExceptions - 在初始调用中添加回调 url
BuildAuthorizeUrl
。
我目前正在做 1. 只是为了让事情正常运行,但显然这不是一个长期的解决方案。我宁愿避免使用回调 url,因为这对于移动应用程序来说似乎过于复杂。
我所追求的是一种让 8.0 项目以与 7.1 项目相同的方式运行的方法。我已经查看了 Dropnet 源代码,其中包含https://api.dropbox.com作为它的基本 URL,所以我更不清楚 7.1 代码是如何工作的。