Skip to content

Commit

Permalink
持续改进 dp2ssl 人脸识别命中多个读者记录功能
Browse files Browse the repository at this point in the history
  • Loading branch information
DigitalPlatform committed Jan 3, 2024
1 parent 6f0a24d commit fa3fe4c
Show file tree
Hide file tree
Showing 16 changed files with 485 additions and 109 deletions.
15 changes: 11 additions & 4 deletions dp2SSL/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2636,8 +2636,8 @@ public static void Invoke(Action action)
public static void ErrorBox(
string title,
string message,
string color = "red",
string style = "")
string color = "red",
string style = "")
{
ProgressWindow progress = null;

Expand All @@ -2659,9 +2659,16 @@ public static void ErrorBox(
progress.Show();
}));

// auto_close:xxx 其中 xxx 为延时秒数。:xxx 缺省为 3 秒
var delay_seconds_string = StringUtil.GetParameterByPrefix(style, "auto_close");

if (StringUtil.IsInList("auto_close", style))
if (/*StringUtil.IsInList("auto_close", style)*/
delay_seconds_string != null)
{
int delay_seconds = 3;
if (string.IsNullOrEmpty(delay_seconds_string) == false)
Int32.TryParse(delay_seconds_string, out delay_seconds);

App.Invoke(new Action(() =>
{
progress.MessageText = message;
Expand All @@ -2674,7 +2681,7 @@ public static void ErrorBox(
try
{
// TODO: 显示倒计时计数?
await Task.Delay(TimeSpan.FromSeconds(1));
await Task.Delay(TimeSpan.FromSeconds(delay_seconds));
App.Invoke(new Action(() =>
{
progress.Close();
Expand Down
6 changes: 3 additions & 3 deletions dp2SSL/Controls/PatronControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@
<TextBlock Grid.Row="3" Grid.Column="1"
Text="姓名"
Foreground="{StaticResource patronNameText}"
Margin="0,4,6,0" FontSize="24" TextAlignment="Right"/>
Margin="0,4,6,0" FontSize="24" FontWeight="Thin" TextAlignment="Right"/>
<!-- 姓名 内容 -->
<TextBlock Grid.Row="3" Grid.Column="3" Text="{Binding PatronNameMasked}"
Foreground="{StaticResource patronHilightText}" TextWrapping="Wrap"
Margin="0,4,6,0" FontSize="24" FontWeight="Bold"/>
Margin="0,4,6,0" FontSize="24" FontWeight="Thin"/>

<!-- 单位 名称 -->
<TextBlock Grid.Row="4" Grid.Column="1" Text="单位"
Expand All @@ -131,7 +131,7 @@
Visibility="{Binding Path=Error, Converter={StaticResource StringToVis}}"
TextWrapping="WrapWithOverflow"/>
<!-- 各种状态 -->
<WrapPanel Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="3" Margin="2">
<WrapPanel Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="3" Margin="0,6,0,4">
<TextBlock Foreground="White" Background="DarkRed"
Margin="0" Padding="6,2,6,2"
Visibility="{Binding State, Converter={StaticResource StringToVis}}"
Expand Down
104 changes: 104 additions & 0 deletions dp2SSL/Dialog/AttackManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using DigitalPlatform;

namespace dp2SSL
{
// 用于防范登录攻击的类
public class AttackManager
{
Hashtable _table = new Hashtable();

// 多少次被当作攻击
public int AttackCount = 5;

// 限制最多条目数
public int LimitCount = 5000;

// 多长时间以上的旧条目要被清除
public TimeSpan CleanLength = TimeSpan.FromMinutes(5);

// 加入一个条目,或者增量已有条目的计数
public void Increase(string title)
{
if (_table.Count > LimitCount)
Clean(CleanLength);

lock (_table.SyncRoot)
{
var entry = _table[title] as AttackEntry;
if (entry == null)
{
// 如果依然超过了限制条目数,只好不再增加新条目
if (_table.Count > LimitCount)
return;

entry = new AttackEntry
{
Title = title,
LastTime = DateTime.Now,
Count = 1
};
_table[title] = entry;
}
else
{
entry.Count++;
entry.LastTime = DateTime.Now;
}
}
}

// 检索,查看指定的 title 是否已经存在对应的条目
public NormalResult Search(string title)
{
lock (_table.SyncRoot)
{
var entry = _table[title] as AttackEntry;
if (entry == null)
return new NormalResult();
if (entry.Count < AttackCount)
return new NormalResult();
return new NormalResult { Value = 1 };
}
}

// 清理超过一定时间的条目
public void Clean(TimeSpan length)
{
lock (_table.SyncRoot)
{
List<string> delete_keys = new List<string>();
DateTime now = DateTime.Now;
foreach (string key in _table.Keys)
{
var entry = _table[key] as AttackEntry;
if (now - entry.LastTime > length)
delete_keys.Add(key);
}

foreach (string key in delete_keys)
{
// TODO: 可以考虑把条目删除前记载到日志文件
_table.Remove(key);
}
}
}
}

class AttackEntry
{
public string Title { get; set; }

// 最后一次攻击的时间
public DateTime LastTime { get; set; }

// 攻击次数
public long Count { get; set; }
}
}
4 changes: 3 additions & 1 deletion dp2SSL/Dialog/ProgressWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
<DropShadowEffect Color="Gray" BlurRadius="20" Direction="-45" RenderingBias="Quality" ShadowDepth="14"/>
</Window.Effect>
<Border BorderThickness="2" BorderBrush="Gray">
<Grid Background="Transparent" Margin="30">
<Grid Name="mainGrid"
Background="Transparent" Margin="30"
KeyDown="Grid_KeyDown" Focusable="True">
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="*"/>
Expand Down
20 changes: 20 additions & 0 deletions dp2SSL/Dialog/ProgressWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public partial class ProgressWindow : Window
public ProgressWindow()
{
InitializeComponent();

this.Loaded += (s, o) => {
this.mainGrid.Focus();
};
}

private void OkButton_Click(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -206,5 +210,21 @@ private void cancelButton_Click(object sender, RoutedEventArgs e)

this.Close();
}

private void Grid_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter
|| e.Key == Key.Space)
{
OkButton_Click(this, new RoutedEventArgs());
return;
}

if (e.Key == Key.Escape)
{
cancelButton_Click(this, new RoutedEventArgs());
return;
}
}
}
}
71 changes: 67 additions & 4 deletions dp2SSL/Dialog/SelectPatronWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
// using System.Windows.Shapes;
using System.Diagnostics;
using System.Xml;
using System.IO;

// using Xceed.Wpf.Toolkit;
using WindowsInput;

using static dp2SSL.LibraryChannelUtil;
Expand Down Expand Up @@ -74,7 +72,13 @@ void OnEnter()
string text = this.password.Password;
if (text.Length < 4)
{
MessageBox.Show(this, "输入的密码长度必须大于等于 4 字符");
// MessageBox.Show(this, "输入的密码长度必须大于等于 4 字符");
App.CurrentApp.Speak($"密码筛选失败");
App.ErrorBox(
"密码筛选",
"输入的密码长度必须大于等于 4 字符",
"red",
"auto_close:5");
return;
}
var result = SelectPatronByPassword(text);
Expand All @@ -83,7 +87,13 @@ void OnEnter()
selectButton_Click(this, new RoutedEventArgs());
return;
}
MessageBox.Show(this, result.ErrorInfo);
// MessageBox.Show(this, result.ErrorInfo);
App.CurrentApp.Speak($"密码筛选失败");
App.ErrorBox(
"密码筛选",
result.ErrorInfo,
"red",
"auto_close:5");
return;
}

Expand All @@ -104,6 +114,9 @@ private void SelectPatronWindow_Loaded(object sender, RoutedEventArgs e)

_ = Task.Factory.StartNew(async () =>
{
// 清理以前较旧的攻击条目
attackManager.Clean(attackManager.CleanLength);

using (CancellationTokenSource cancel = CancellationTokenSource.CreateLinkedTokenSource(_cancel.Token, App.CancelToken))
{
var result = await FillPatronCollectionDetailAsync(
Expand Down Expand Up @@ -346,6 +359,12 @@ NormalResult SelectPatronByPassword(string password)
this.passwordArea.IsEnabled = true;
}

if (HasAttacked() == true)
return new NormalResult
{
Value = -1,
ErrorInfo = "因失败次数太多,相关人脸信息已经进入保护状态,请稍后再重试操作 ..."
};
try
{
// this.listView.SelectedItem = null;
Expand Down Expand Up @@ -382,11 +401,14 @@ NormalResult SelectPatronByPassword(string password)
}

if (hits.Count == 0)
{
MemoryAttack();
return new NormalResult
{
Value = 0,
ErrorInfo = "没有匹配的读者"
};
}

if (hits.Count == 1)
{
Expand All @@ -395,6 +417,7 @@ NormalResult SelectPatronByPassword(string password)
}

Debug.Assert(hits.Count > 1);
MemoryAttack();
return new NormalResult
{
Value = hits.Count,
Expand Down Expand Up @@ -598,6 +621,46 @@ void OnVisibleChanged()
this.mainGrid.ColumnDefinitions[1].Width = new GridLength(330);
}
}

static AttackManager attackManager = new AttackManager();

void MemoryAttack()
{
foreach (var patron in _patrons)
{
attackManager.Increase(patron.PII);
}
}

// 检测是否因为以前攻击而处在监控期间
public static bool HasAttacked(List<string> barcode_list)
{
foreach (var barcode in barcode_list)
{
var result = attackManager.Search(barcode);
if (result.Value == 1)
return true;
}

return false;
}

bool HasAttacked()
{
List<string> barcodes = new List<string>();
foreach(var patron in _patrons)
{
barcodes.Add(patron.PII);
}

return HasAttacked(barcodes);
}

public static void CleanAttackManager()
{
// 清理以前较旧的攻击条目
attackManager.Clean(attackManager.CleanLength);
}
}

public class PatronCollection : ObservableCollection<Patron>
Expand Down
Loading

0 comments on commit fa3fe4c

Please sign in to comment.