修离线缓存

This commit is contained in:
lanyi 2021-10-19 23:13:28 +02:00
parent 888ddce4ef
commit 6f5c21aa8f
6 changed files with 53 additions and 28 deletions

View File

@ -11,7 +11,7 @@ namespace AnotherReplayReader
public About() public About()
{ {
InitializeComponent(); InitializeComponent();
_idBox.Text = Auth.ID; _idBox.Text = Auth.Id;
} }
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)

22
Auth.cs
View File

@ -9,11 +9,11 @@ namespace AnotherReplayReader
{ {
internal static class Auth internal static class Auth
{ {
public static string? ID { get; } public static string? Id { get; }
static Auth() static Auth()
{ {
ID = null; Id = null;
string? windowsID; string? windowsID;
try try
@ -56,17 +56,17 @@ namespace AnotherReplayReader
using var sha = SHA256.Create(); using var sha = SHA256.Create();
var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(windowsID + randomKey)); var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(windowsID + randomKey));
ID = string.Concat(hash.Skip(3).Take(10).Select(x => $"{x:X2}")); Id = string.Concat(hash.Skip(3).Take(10).Select(x => $"{x:X2}"));
} }
public static string GetKey() public static string GetKey()
{ {
if (ID == null) if (Id == null)
{ {
return string.Empty; return string.Empty;
} }
var text = $"{ID}{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}"; var text = $"{Id}{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
var bytes = Encoding.UTF8.GetBytes(text); var bytes = Encoding.UTF8.GetBytes(text);
var pre = Encoding.UTF8.GetBytes("playertable!"); var pre = Encoding.UTF8.GetBytes("playertable!");
var salt = new byte[9]; var salt = new byte[9];
@ -82,5 +82,17 @@ namespace AnotherReplayReader
return Convert.ToBase64String(salt.Concat(bytes).Select((x, i) => (byte)(x ^ pre[i % pre.Length])).ToArray()); return Convert.ToBase64String(salt.Concat(bytes).Select((x, i) => (byte)(x ^ pre[i % pre.Length])).ToArray());
} }
public static byte[]? IdAsKey()
{
if (string.IsNullOrEmpty(Id))
{
return null;
}
var bytes = Encoding.UTF8.GetBytes(Id);
var destination = Enumerable.Repeat<byte>(0xEA, 24).ToArray();
Array.Copy(bytes, destination, Math.Min(bytes.Length, destination.Length));
return destination;
}
} }
} }

View File

@ -14,9 +14,11 @@ namespace AnotherReplayReader
private readonly ConcurrentDictionary<string, string> _storage = new(); private readonly ConcurrentDictionary<string, string> _storage = new();
public Task Initialization { get; }
public Cache() public Cache()
{ {
Task.Run(async () => Initialization = Task.Run(async () =>
{ {
try try
{ {

View File

@ -86,17 +86,19 @@ namespace AnotherReplayReader
_list = converted; _list = converted;
} }
if (list is null) if (list is null || Auth.IdAsKey() is not { } encryptKey)
{ {
_cache.Set<string?>(StoredKey, null); _cache.Set<string?>(StoredKey, null);
return; return;
} }
using var aes = Aes.Create();
using var encryptor = aes.CreateEncryptor(Encoding.UTF8.GetBytes(Auth.ID), aes.IV);
using var memory = new MemoryStream(); using var memory = new MemoryStream();
using var decryptorStream = new CryptoStream(memory, encryptor, CryptoStreamMode.Write); using var aes = Aes.Create();
await SerializeAsync(decryptorStream, list, _jsonOptions).ConfigureAwait(false); using (var encryptor = aes.CreateEncryptor(encryptKey, aes.IV))
using (var decryptorStream = new CryptoStream(memory, encryptor, CryptoStreamMode.Write))
{
await SerializeAsync(decryptorStream, list, _jsonOptions).ConfigureAwait(false);
}
memory.Flush(); memory.Flush();
_cache.SetValues((StoredKey, Convert.ToBase64String(memory.ToArray())), (IvKey, Convert.ToBase64String(aes.IV))); _cache.SetValues((StoredKey, Convert.ToBase64String(memory.ToArray())), (IvKey, Convert.ToBase64String(aes.IV)));
} }
@ -155,15 +157,16 @@ namespace AnotherReplayReader
{ {
try try
{ {
await _cache.Initialization;
var stored = _cache.GetOrDefault(StoredKey, string.Empty); var stored = _cache.GetOrDefault(StoredKey, string.Empty);
var iv = Convert.FromBase64String(_cache.GetOrDefault(IvKey, string.Empty)); var iv = Convert.FromBase64String(_cache.GetOrDefault(IvKey, string.Empty));
if (string.IsNullOrWhiteSpace(stored)) if (string.IsNullOrWhiteSpace(stored) || Auth.IdAsKey() is not { } key)
{ {
return; return;
} }
using var aes = Aes.Create(); using var aes = Aes.Create();
using var decryptor = aes.CreateDecryptor(Encoding.UTF8.GetBytes(Auth.ID), iv); using var decryptor = aes.CreateDecryptor(key, iv);
using var memory = new MemoryStream(Convert.FromBase64String(stored)); using var memory = new MemoryStream(Convert.FromBase64String(stored));
using var decryptorStream = new CryptoStream(memory, decryptor, CryptoStreamMode.Read); using var decryptorStream = new CryptoStream(memory, decryptor, CryptoStreamMode.Read);
var cachedTable = await DeserializeAsync<List<IpAndPlayer>>(decryptorStream, _jsonOptions).ConfigureAwait(false); var cachedTable = await DeserializeAsync<List<IpAndPlayer>>(decryptorStream, _jsonOptions).ConfigureAwait(false);

View File

@ -13,7 +13,11 @@
<TextBox x:Name="_idField" Height="16" Margin="294,27,92,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" TextChanged="OnIpFieldChanged" /> <TextBox x:Name="_idField" Height="16" Margin="294,27,92,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" TextChanged="OnIpFieldChanged" />
<TextBlock x:Name="textBlock1" HorizontalAlignment="Left" Margin="205,28,0,0" TextWrapping="Wrap" Text="玩家名称 / 说明" VerticalAlignment="Top"/> <TextBlock x:Name="textBlock1" HorizontalAlignment="Left" Margin="205,28,0,0" TextWrapping="Wrap" Text="玩家名称 / 说明" VerticalAlignment="Top"/>
<Button x:Name="_setIPButton" Content="上传" Margin="705,26,12,0" VerticalAlignment="Top" Click="OnClick"/> <Button x:Name="_setIPButton" Content="上传" Margin="705,26,12,0" VerticalAlignment="Top" Click="OnClick"/>
<DataGrid x:Name="_dataGrid" Margin="20,60,12,19" MouseDoubleClick="DataGrid_MouseDoubleClick" IsReadOnly="True"> <DataGrid x:Name="_dataGrid"
Margin="20,60,12,19"
MouseDoubleClick="DataGrid_MouseDoubleClick"
IsReadOnly="True"
AutoGenerateColumns="False">
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="IP" Binding="{Binding Path=IpString}"/> <DataGridTextColumn Header="IP" Binding="{Binding Path=IpString}"/>
<DataGridTextColumn Header="玩家名称 / 说明" Binding="{Binding Path=Id}"/> <DataGridTextColumn Header="玩家名称 / 说明" Binding="{Binding Path=Id}"/>

View File

@ -1,5 +1,7 @@
using AnotherReplayReader.Utils; using AnotherReplayReader.Utils;
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -20,16 +22,21 @@ namespace AnotherReplayReader
{ {
InitializeComponent(); InitializeComponent();
_identity = identity; _identity = identity;
Refresh(); Refresh(true);
} }
private async void Refresh() private async void Refresh(bool showCached)
{ {
_setIPButton.IsEnabled = false; _setIPButton.IsEnabled = false;
try try
{ {
_dataGrid.Items.Clear(); var loading = new IpAndPlayer[] { new() { Ip = 0, Id = "正在加载..." } };
_dataGrid.Items.Add(new IpAndPlayer { Ip = 0, Id = "正在加载..." }); _dataGrid.ItemsSource = loading;
if (showCached)
{
await Display();
_dataGrid.ItemsSource = loading.Concat(_dataGrid.ItemsSource.Cast<IpAndPlayer>());
}
await _identity.Fetch(); await _identity.Fetch();
await Display(); await Display();
} }
@ -45,10 +52,10 @@ namespace AnotherReplayReader
private async Task Display(string filter = "", string nameFilter = "") private async Task Display(string filter = "", string nameFilter = "")
{ {
var newList = await Task.Run(() => var result = await Task.Run(() =>
{ {
var pinyin = nameFilter.ToPinyin(); var pinyin = nameFilter.ToPinyin();
return _identity var query = _identity
.AsSortedList() .AsSortedList()
.Where(x => .Where(x =>
{ {
@ -61,13 +68,10 @@ namespace AnotherReplayReader
return true; return true;
} }
return x.Id.ContainsIgnoreCase(nameFilter); return x.Id.ContainsIgnoreCase(nameFilter);
}) });
.ToArray(); return new ObservableCollection<IpAndPlayer>(query);
}); });
_dataGrid.ItemsSource = result;
_dataGrid.Items.Clear();
_dataGrid.ItemsSource = newList;
_dataGrid.Items.Refresh();
} }
private async void OnClick(object sender, RoutedEventArgs e) private async void OnClick(object sender, RoutedEventArgs e)
@ -97,7 +101,7 @@ namespace AnotherReplayReader
MessageBox.Show(this, "设置 IP 表失败"); MessageBox.Show(this, "设置 IP 表失败");
} }
Refresh(); Refresh(false);
} }
catch (Exception exception) catch (Exception exception)
{ {