我目前正在尝试将手机示例应用程序从官方 ADAL github存储库转换为 caliburn.micro MVVM 应用程序。但是,为了与WebAuthenticationBroker相处,代码隐藏中有太多移动部件,我现在不知道如何在代理登录后再次激活应用程序时将其推送到视图模型中并正确处理导航。由于我目前完全一无所知,因此还没有代码可以分享。
1 回答
我一直在我的 Windows Phone 8.1 应用程序中使用 MvvmLight 和 ADAL。您需要做的是,一旦获得令牌,您需要使用 Messenger 模式发送消息。所有需要令牌并且已经订阅它的视图模型都会收到它。这是我在我的应用程序中使用 MvvmLight 所做的事情。请记住,您需要有一个 ContinuationManager 类和 IWebContinuable 接口才能使应用程序正常工作。
private async void Login()
{
AuthenticationResult result = null;
context = AuthenticationContext.CreateAsync("https://login.windows.net/<tenant-id>").GetResults();
try
{
//try to check if you can get the token without showing pop-up
result = await context.AcquireTokenSilentAsync("https://management.core.windows.net/", "<clientid>");
if(result.Status==AuthenticationStatus.ClientError)
{
bool exists = CheckInVault();
if(exists)
{
PasswordVault vault = new PasswordVault();
var tokenvault = vault.FindAllByResource("Token");
string RefreshToken = tokenvault[0].Password;
var refresh=await context.AcquireTokenByRefreshTokenAsync(RefreshToken, clientid);
vault.Remove(tokenvault[0]);
StoreToken(refresh);
}
else
{
context.AcquireTokenAndContinue("https://management.core.windows.net/", clientid, WebAuthenticationBroker.GetCurrentApplicationCallbackUri(), StoreToken);
}
}
else if(result != null && result.Status == AuthenticationStatus.Success)
{
// A token was successfully retrieved. Post the new To Do item
bool exists = CheckInVault();
if (exists)
{
PasswordVault vault = new PasswordVault();
var tokenvault = vault.FindAllByResource("Token");
vault.Remove(tokenvault[0]);
}
StoreToken(result);
}
//this method will be called when app is opened first time and pop-up appears
result=await context.AcquireTokenSilentAsync("https://management.core.windows.net/", "<client-id>");
}
catch(Exception e)
{
MessageDialog dialog = new MessageDialog("Error");
}
}
我在这里做的是——在用户第一次注册时获取访问令牌和引用令牌后,我将刷新令牌存储在 PasswordVault 中,以便将来获取它以启用单点登录。ADAL 实际上确实使用了它的缓存功能,但有时单点登录对我来说失败了,因此使用 PasswordVault 来存储刷新令牌。身份验证完成后,我有一个 StoreToken 函数的委托,我实际存储新的刷新令牌并使用 MvvmLight 中的 Messenger 类将访问令牌发送给所有订阅者。
private void StoreToken(AuthenticationResult result)
{
try
{
var token = result.AccessToken;
Messenger.Default.Send<string>(token); //send the access token.
PasswordVault vault = new PasswordVault();
PasswordCredential credential = new PasswordCredential();
credential.UserName = result.AccessToken;
credential.Password = result.RefreshToken;
credential.Resource = "Token";
vault.Add(credential);
}
catch(Exception e)
{
}
}
我建议在视图模型中处理导航。定义一个辅助类,如 NavigationService:
public class NavigationService:INavigationService
{
private Frame _frame;
public Frame Frame
{
get
{
return _frame;
}
set
{
_frame = value;
_frame.Navigated+= OnFrameNavigated;
}
}
public void NavigateTo(string type)
{
Frame.Navigate(Type.GetType(type));
}
public void GoForward()
{
if (Frame.CanGoForward)
Frame.GoForward();
}
public void GoBack()
{
if (Frame.CanGoBack)
Frame.GoBack();
}
}
要从视图模型导航到页面,请使用 NavigateTo(string) 方法
NavigateTo("<fully qualified class name of the page you want to navigate to>,<assembly name>")
我还建议使用 IoC 容器(MvvmLight 为您提供 ViewModelLocator 类),以便您可以维护视图模型的单例实例和 NavigationService 等助手。我没有使用过 CaliburnMicro 框架,但我认为消息传递和依赖注入会有类似的功能。