Xamarin 中的离线身份验证最佳实践
Offline authentication best practices in Xamarin
我打算创建一个 Xamarin(.Forms) 应用程序,它必须具有身份验证:用户应提供用户名和密码才能获取数据。
问题是它也必须离线工作(这意味着它不应该依赖服务器进行身份验证过程)。
到目前为止我考虑了以下几点:
- 在首选项中存储用户名和密码 - 未加密、易于重置、易于获取等
- 在数据库中存储用户名和密码 - 可以加密(我想),易于重置
最佳做法是什么? Xamarin 是否有任何内置解决方案?
这取决于您的应用需求——如果您只需要对用户进行身份验证以离线访问某些受限数据——我建议您对用户名和密码进行哈希处理,并将其存储在本地设备中(无关紧要)在哪里,它被散列了)。
如果您稍后需要使用用户名和密码来通过服务器对其进行身份验证,那么您应该使用安全数据,如钥匙串,Xamarin 有一个内置的抽象来使用它,它被称为 Xamarin.Auth ,您可以在其中安全地存储您的凭据。
*注意 - 在 jailbroken/rooted 设备中存储敏感数据存在风险,请谨慎使用。
编辑 - 我已经添加了一个关于如何消费和使用这些服务的工作代码示例:
1) 在您的可移植项目中添加此接口:
public interface ISecuredDataProvider
{
void Store(string userId, string providerName, IDictionary<string, string> data);
void Clear(string providerName);
Dictionary<string, string> Retreive(string providerName);
}
2) 在您的 Android 项目中,添加此实现:
public class AndroidSecuredDataProvider : ISecuredDataProvider
{
public void Store(string userId, string providerName, IDictionary<string, string> data)
{
Clear(providerName);
var accountStore = AccountStore.Create(Android.App.Application.Context);
var account = new Account(userId, data);
accountStore.Save(account, providerName);
}
public void Clear(string providerName)
{
var accountStore = AccountStore.Create(Android.App.Application.Context);
var accounts = accountStore.FindAccountsForService(providerName);
foreach (var account in accounts)
{
accountStore.Delete(account, providerName);
}
}
public Dictionary<string, string> Retreive(string providerName)
{
var accountStore = AccountStore.Create(Android.App.Application.Context);
var accounts = accountStore.FindAccountsForService(providerName).FirstOrDefault();
return (accounts != null) ? accounts.Properties : new Dictionary<string, string>();
}
}
3) 在您的 iOS 项目中,添加此实现:
public class IOSSecuredDataProvider : ISecuredDataProvider
{
public void Store(string userId, string providerName, IDictionary<string, string> data)
{
Clear(providerName);
var accountStore = AccountStore.Create();
var account = new Account(userId, data);
accountStore.Save(account, providerName);
}
public void Clear(string providerName)
{
var accountStore = AccountStore.Create();
var accounts = accountStore.FindAccountsForService(providerName);
foreach (var account in accounts)
{
accountStore.Delete(account, providerName);
}
}
public Dictionary<string, string> Retreive(string providerName)
{
var accountStore = AccountStore.Create();
var accounts = accountStore.FindAccountsForService(providerName).FirstOrDefault();
return (accounts != null) ? accounts.Properties : new Dictionary<string, string>();
}
}
4) 用法示例 - 在获取 facebook 令牌后,我们将像这样存储它:
securedDataProvider.Store(user.Id, "FacebookAuth", new Dictionary<string, string> { { "FacebookToken", token } });
注意 - 我添加了两层数据,以便让第一层表明身份验证是否为 Facebook/UserName-Password/other。
第二层是数据本身——即 facebook 令牌/凭证。
我打算创建一个 Xamarin(.Forms) 应用程序,它必须具有身份验证:用户应提供用户名和密码才能获取数据。
问题是它也必须离线工作(这意味着它不应该依赖服务器进行身份验证过程)。
到目前为止我考虑了以下几点:
- 在首选项中存储用户名和密码 - 未加密、易于重置、易于获取等
- 在数据库中存储用户名和密码 - 可以加密(我想),易于重置
最佳做法是什么? Xamarin 是否有任何内置解决方案?
这取决于您的应用需求——如果您只需要对用户进行身份验证以离线访问某些受限数据——我建议您对用户名和密码进行哈希处理,并将其存储在本地设备中(无关紧要)在哪里,它被散列了)。
如果您稍后需要使用用户名和密码来通过服务器对其进行身份验证,那么您应该使用安全数据,如钥匙串,Xamarin 有一个内置的抽象来使用它,它被称为 Xamarin.Auth ,您可以在其中安全地存储您的凭据。
*注意 - 在 jailbroken/rooted 设备中存储敏感数据存在风险,请谨慎使用。
编辑 - 我已经添加了一个关于如何消费和使用这些服务的工作代码示例:
1) 在您的可移植项目中添加此接口:
public interface ISecuredDataProvider
{
void Store(string userId, string providerName, IDictionary<string, string> data);
void Clear(string providerName);
Dictionary<string, string> Retreive(string providerName);
}
2) 在您的 Android 项目中,添加此实现:
public class AndroidSecuredDataProvider : ISecuredDataProvider
{
public void Store(string userId, string providerName, IDictionary<string, string> data)
{
Clear(providerName);
var accountStore = AccountStore.Create(Android.App.Application.Context);
var account = new Account(userId, data);
accountStore.Save(account, providerName);
}
public void Clear(string providerName)
{
var accountStore = AccountStore.Create(Android.App.Application.Context);
var accounts = accountStore.FindAccountsForService(providerName);
foreach (var account in accounts)
{
accountStore.Delete(account, providerName);
}
}
public Dictionary<string, string> Retreive(string providerName)
{
var accountStore = AccountStore.Create(Android.App.Application.Context);
var accounts = accountStore.FindAccountsForService(providerName).FirstOrDefault();
return (accounts != null) ? accounts.Properties : new Dictionary<string, string>();
}
}
3) 在您的 iOS 项目中,添加此实现:
public class IOSSecuredDataProvider : ISecuredDataProvider
{
public void Store(string userId, string providerName, IDictionary<string, string> data)
{
Clear(providerName);
var accountStore = AccountStore.Create();
var account = new Account(userId, data);
accountStore.Save(account, providerName);
}
public void Clear(string providerName)
{
var accountStore = AccountStore.Create();
var accounts = accountStore.FindAccountsForService(providerName);
foreach (var account in accounts)
{
accountStore.Delete(account, providerName);
}
}
public Dictionary<string, string> Retreive(string providerName)
{
var accountStore = AccountStore.Create();
var accounts = accountStore.FindAccountsForService(providerName).FirstOrDefault();
return (accounts != null) ? accounts.Properties : new Dictionary<string, string>();
}
}
4) 用法示例 - 在获取 facebook 令牌后,我们将像这样存储它:
securedDataProvider.Store(user.Id, "FacebookAuth", new Dictionary<string, string> { { "FacebookToken", token } });
注意 - 我添加了两层数据,以便让第一层表明身份验证是否为 Facebook/UserName-Password/other。 第二层是数据本身——即 facebook 令牌/凭证。