修改BUG:在线用户与IP地址统一使用1分钟过期处理 closed #IUUZ3
#Issue https://gitee.com/LongbowEnterprise/dashboard/issues?id=IUUZ3 #Comment 统一使用Longbow.Cache.AutoExpireCacheEntry类处理
This commit is contained in:
parent
87395f0376
commit
68c3ebcd82
|
@ -1,8 +1,11 @@
|
||||||
using Bootstrap.DataAccess;
|
using Bootstrap.DataAccess;
|
||||||
|
using Longbow.Cache;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -14,10 +17,10 @@ namespace Bootstrap.Admin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class DefaultOnlineUsers : IOnlineUsers
|
internal class DefaultOnlineUsers : IOnlineUsers
|
||||||
{
|
{
|
||||||
private ConcurrentDictionary<string, OnlineUserCache> _onlineUsers = new ConcurrentDictionary<string, OnlineUserCache>();
|
private readonly ConcurrentDictionary<string, AutoExpireCacheEntry<OnlineUser>> _onlineUsers = new ConcurrentDictionary<string, AutoExpireCacheEntry<OnlineUser>>();
|
||||||
private ConcurrentDictionary<string, string> _ipLocator = new ConcurrentDictionary<string, string>();
|
private readonly ConcurrentDictionary<string, AutoExpireCacheEntry<string>> _ipLocator = new ConcurrentDictionary<string, AutoExpireCacheEntry<string>>();
|
||||||
private HttpClient _client;
|
private readonly HttpClient _client;
|
||||||
private IEnumerable<string> _local = new string[] { "::1", "127.0.0.1" };
|
private readonly IEnumerable<string> _local = new string[] { "::1", "127.0.0.1" };
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -33,7 +36,7 @@ namespace Bootstrap.Admin
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public IEnumerable<OnlineUser> OnlineUsers
|
public IEnumerable<OnlineUser> OnlineUsers
|
||||||
{
|
{
|
||||||
get { return _onlineUsers.Values.Select(v => v.User); }
|
get { return _onlineUsers.Values.Select(v => v.Value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -43,7 +46,7 @@ namespace Bootstrap.Admin
|
||||||
/// <param name="addValueFactory"></param>
|
/// <param name="addValueFactory"></param>
|
||||||
/// <param name="updateValueFactory"></param>
|
/// <param name="updateValueFactory"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public OnlineUserCache AddOrUpdate(string key, Func<string, OnlineUserCache> addValueFactory, Func<string, OnlineUserCache, OnlineUserCache> updateValueFactory) => _onlineUsers.AddOrUpdate(key, addValueFactory, updateValueFactory);
|
public AutoExpireCacheEntry<OnlineUser> AddOrUpdate(string key, Func<string, AutoExpireCacheEntry<OnlineUser>> addValueFactory, Func<string, AutoExpireCacheEntry<OnlineUser>, AutoExpireCacheEntry<OnlineUser>> updateValueFactory) => _onlineUsers.AddOrUpdate(key, addValueFactory, updateValueFactory);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
@ -51,34 +54,44 @@ namespace Bootstrap.Admin
|
||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <param name="onlineUserCache"></param>
|
/// <param name="onlineUserCache"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool TryRemove(string key, out OnlineUserCache onlineUserCache) => _onlineUsers.TryRemove(key, out onlineUserCache);
|
public bool TryRemove(string key, out AutoExpireCacheEntry<OnlineUser> onlineUserCache) => _onlineUsers.TryRemove(key, out onlineUserCache);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ip"></param>
|
/// <param name="ip"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public string RetrieveLocaleByIp(string ip = null)
|
public string RetrieveLocaleByIp(string ip = null) => _ipLocator.GetOrAdd(ip, key => new AutoExpireCacheEntry<string>(IPProxy(key), 1000 * 60, __ => _ipLocator.TryRemove(key, out _))).Value;
|
||||||
{
|
|
||||||
|
private string IPProxy(string ip)
|
||||||
|
{
|
||||||
var ipSvr = DictHelper.RetrieveLocaleIPSvr();
|
var ipSvr = DictHelper.RetrieveLocaleIPSvr();
|
||||||
if (ipSvr.IsNullOrEmpty() || ipSvr.Equals("None", StringComparison.OrdinalIgnoreCase) || ip.IsNullOrEmpty() || _local.Any(p => p == ip)) return "本地连接";
|
if (ipSvr.IsNullOrEmpty() || ipSvr.Equals("None", StringComparison.OrdinalIgnoreCase) || ip.IsNullOrEmpty() || _local.Any(p => p == ip)) return "本地连接";
|
||||||
|
|
||||||
return _ipLocator.GetOrAdd(ip, key =>
|
var ipSvrUrl = DictHelper.RetrieveLocaleIPSvrUrl(ipSvr);
|
||||||
{
|
if (ipSvrUrl.IsNullOrEmpty()) return "本地连接";
|
||||||
var ipSvrUrl = DictHelper.RetrieveLocaleIPSvrUrl(ipSvr);
|
|
||||||
if (ipSvrUrl.IsNullOrEmpty()) return "本地连接";
|
var url = $"{ipSvrUrl}{ip}";
|
||||||
|
var task = ipSvr == "BaiDuIPSvr" ? RetrieveLocator<BaiDuIPLocator>(url) : RetrieveLocator<JuheIPLocator>(url);
|
||||||
var url = $"{ipSvrUrl}{ip}";
|
task.Wait();
|
||||||
var task = ipSvr == "BaiDuIPSvr" ? RetrieveLocator<BaiDuIPLocator>(url) : RetrieveLocator<JuheIPLocator>(url);
|
return task.Result;
|
||||||
task.Wait();
|
|
||||||
return task.Result;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> RetrieveLocator<T>(string url)
|
private async Task<string> RetrieveLocator<T>(string url)
|
||||||
{
|
{
|
||||||
var result = await _client.GetAsJsonAsync<T>(url);
|
var ret = default(T);
|
||||||
return result.ToString();
|
try
|
||||||
|
{
|
||||||
|
ret = await _client.GetAsJsonAsync<T>(url);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ex.Log(new NameValueCollection()
|
||||||
|
{
|
||||||
|
["Url"] = url
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ret?.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using Longbow.Cache;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Bootstrap.Admin
|
namespace Bootstrap.Admin
|
||||||
|
@ -20,7 +21,7 @@ namespace Bootstrap.Admin
|
||||||
/// <param name="addValueFactory"></param>
|
/// <param name="addValueFactory"></param>
|
||||||
/// <param name="updateValueFactory"></param>
|
/// <param name="updateValueFactory"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
OnlineUserCache AddOrUpdate(string key, Func<string, OnlineUserCache> addValueFactory, Func<string, OnlineUserCache, OnlineUserCache> updateValueFactory);
|
AutoExpireCacheEntry<OnlineUser> AddOrUpdate(string key, Func<string, AutoExpireCacheEntry<OnlineUser>> addValueFactory, Func<string, AutoExpireCacheEntry<OnlineUser>, AutoExpireCacheEntry<OnlineUser>> updateValueFactory);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
@ -28,7 +29,7 @@ namespace Bootstrap.Admin
|
||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <param name="onlineUserCache"></param>
|
/// <param name="onlineUserCache"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
bool TryRemove(string key, out OnlineUserCache onlineUserCache);
|
bool TryRemove(string key, out AutoExpireCacheEntry<OnlineUser> onlineUserCache);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Bootstrap.Admin
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class OnlineUserCache : IDisposable
|
|
||||||
{
|
|
||||||
private Timer dispatcher;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user"></param>
|
|
||||||
/// <param name="action"></param>
|
|
||||||
public OnlineUserCache(OnlineUser user, Action action)
|
|
||||||
{
|
|
||||||
User = user;
|
|
||||||
dispatcher = new Timer(_ => action(), null, TimeSpan.FromMinutes(1), Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public OnlineUser User { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
if (dispatcher != null) dispatcher.Change(TimeSpan.FromMinutes(1), Timeout.InfiniteTimeSpan);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Impletement IDispose
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing"></param>
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
if (dispatcher != null)
|
|
||||||
{
|
|
||||||
dispatcher.Dispose();
|
|
||||||
dispatcher = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Bootstrap.Admin;
|
using Bootstrap.Admin;
|
||||||
using Bootstrap.DataAccess;
|
using Bootstrap.DataAccess;
|
||||||
|
using Longbow.Cache;
|
||||||
using Longbow.Web;
|
using Longbow.Web;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@ -27,9 +28,9 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
if (user == null) return;
|
if (user == null) return;
|
||||||
|
|
||||||
var onlineUserSvr = context.RequestServices.GetRequiredService<IOnlineUsers>();
|
var onlineUserSvr = context.RequestServices.GetRequiredService<IOnlineUsers>();
|
||||||
var proxy = new Func<OnlineUserCache, Action, OnlineUserCache>((c, action) =>
|
var proxy = new Func<AutoExpireCacheEntry<OnlineUser>, Action, AutoExpireCacheEntry<OnlineUser>>((c, action) =>
|
||||||
{
|
{
|
||||||
var v = c.User;
|
var v = c.Value;
|
||||||
v.UserName = user.UserName;
|
v.UserName = user.UserName;
|
||||||
v.DisplayName = user.DisplayName;
|
v.DisplayName = user.DisplayName;
|
||||||
v.LastAccessTime = DateTime.Now;
|
v.LastAccessTime = DateTime.Now;
|
||||||
|
@ -50,7 +51,7 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
v.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
v.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
||||||
v.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
v.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
||||||
v.FirstAccessTime = DateTime.Now;
|
v.FirstAccessTime = DateTime.Now;
|
||||||
return proxy(new OnlineUserCache(v, () => onlineUserSvr.TryRemove(key, out _)), null);
|
return proxy(new AutoExpireCacheEntry<OnlineUser>(v, 1000 * 60, __ => onlineUserSvr.TryRemove(key, out _)), null);
|
||||||
}, (key, v) => proxy(v, () => v.Reset()));
|
}, (key, v) => proxy(v, () => v.Reset()));
|
||||||
});
|
});
|
||||||
await next();
|
await next();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.1.0" />
|
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.1.0" />
|
||||||
<PackageReference Include="Longbow.Cache" Version="2.2.3" />
|
<PackageReference Include="Longbow.Cache" Version="2.2.4" />
|
||||||
<PackageReference Include="Longbow.Data" Version="2.2.6" />
|
<PackageReference Include="Longbow.Data" Version="2.2.6" />
|
||||||
<PackageReference Include="Longbow.Web" Version="2.2.8" />
|
<PackageReference Include="Longbow.Web" Version="2.2.8" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Bootstrap.Security.Mvc" Version="2.2.4" />
|
<PackageReference Include="Bootstrap.Security.Mvc" Version="2.2.4" />
|
||||||
<PackageReference Include="Longbow.Cache" Version="2.2.3" />
|
|
||||||
<PackageReference Include="Longbow.Logging" Version="2.2.6" />
|
<PackageReference Include="Longbow.Logging" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<PackageReference Include="Longbow.Data" Version="2.2.6" />
|
<PackageReference Include="Longbow.Data" Version="2.2.6" />
|
||||||
<PackageReference Include="Longbow.Security.Cryptography" Version="1.3.0" />
|
<PackageReference Include="Longbow.Security.Cryptography" Version="1.3.0" />
|
||||||
<PackageReference Include="Longbow.Web" Version="2.2.8" />
|
<PackageReference Include="Longbow.Web" Version="2.2.8" />
|
||||||
<PackageReference Include="Longbow.Cache" Version="2.2.3" />
|
<PackageReference Include="Longbow.Cache" Version="2.2.4" />
|
||||||
<PackageReference Include="Longbow" Version="2.2.7" />
|
<PackageReference Include="Longbow" Version="2.2.7" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue