升级组件:Longbow.Web升级到2.2.9
#Comment OnlineUser功能整合到Longbow.Web组件中
This commit is contained in:
parent
32894af881
commit
53900a563a
|
@ -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>
|
||||||
|
|
|
@ -41,13 +41,14 @@ namespace Bootstrap.Admin.Controllers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The login.</returns>
|
/// <returns>The login.</returns>
|
||||||
/// <param name="onlineUserSvr"></param>
|
/// <param name="onlineUserSvr"></param>
|
||||||
|
/// <param name="ipLocator"></param>
|
||||||
/// <param name="userName">User name.</param>
|
/// <param name="userName">User name.</param>
|
||||||
/// <param name="password">Password.</param>
|
/// <param name="password">Password.</param>
|
||||||
/// <param name="remember">Remember.</param>
|
/// <param name="remember">Remember.</param>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Login([FromServices]IOnlineUsers onlineUserSvr, string userName, string password, string remember)
|
public async Task<IActionResult> Login([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, string userName, string password, string remember)
|
||||||
{
|
{
|
||||||
if (UserHelper.Authenticate(userName, password, loginUser => CreateLoginUser(onlineUserSvr, HttpContext, loginUser)))
|
if (UserHelper.Authenticate(userName, password, loginUser => CreateLoginUser(onlineUserSvr, ipLocator, HttpContext, loginUser)))
|
||||||
{
|
{
|
||||||
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
|
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
|
||||||
|
@ -63,13 +64,14 @@ namespace Bootstrap.Admin.Controllers
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onlineUserSvr"></param>
|
/// <param name="onlineUserSvr"></param>
|
||||||
|
/// <param name="ipLocator"></param>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <param name="loginUser"></param>
|
/// <param name="loginUser"></param>
|
||||||
internal static void CreateLoginUser(IOnlineUsers onlineUserSvr, HttpContext context, LoginUser loginUser)
|
internal static void CreateLoginUser(IOnlineUsers onlineUserSvr, IIPLocatorProvider ipLocator, HttpContext context, LoginUser loginUser)
|
||||||
{
|
{
|
||||||
var agent = new UserAgent(context.Request.Headers["User-Agent"]);
|
var agent = new UserAgent(context.Request.Headers["User-Agent"]);
|
||||||
loginUser.Ip = (context.Connection.RemoteIpAddress ?? IPAddress.IPv6Loopback).ToString();
|
loginUser.Ip = (context.Connection.RemoteIpAddress ?? IPAddress.IPv6Loopback).ToString();
|
||||||
loginUser.City = onlineUserSvr.RetrieveLocaleByIp(loginUser.Ip);
|
loginUser.City = ipLocator.Locate(loginUser.Ip);
|
||||||
loginUser.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
loginUser.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
||||||
loginUser.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
loginUser.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Bootstrap.DataAccess;
|
using Bootstrap.DataAccess;
|
||||||
using Bootstrap.Security;
|
using Bootstrap.Security;
|
||||||
|
using Longbow.Web;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
@ -28,17 +29,18 @@ namespace Bootstrap.Admin.Controllers.Api
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onlineUserSvr"></param>
|
/// <param name="onlineUserSvr"></param>
|
||||||
|
/// <param name="ipLocator"></param>
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public string Post([FromServices]IOnlineUsers onlineUserSvr, [FromBody]JObject value)
|
public string Post([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, [FromBody]JObject value)
|
||||||
{
|
{
|
||||||
string token = null;
|
string token = null;
|
||||||
dynamic user = value;
|
dynamic user = value;
|
||||||
string userName = user.userName;
|
string userName = user.userName;
|
||||||
string password = user.password;
|
string password = user.password;
|
||||||
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password) && UserHelper.Authenticate(userName, password, loginUser => AccountController.CreateLoginUser(onlineUserSvr, HttpContext, loginUser)))
|
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password) && UserHelper.Authenticate(userName, password, loginUser => AccountController.CreateLoginUser(onlineUserSvr, ipLocator, HttpContext, loginUser)))
|
||||||
{
|
{
|
||||||
token = BootstrapAdminJwtTokenHandler.CreateToken(userName);
|
token = BootstrapAdminJwtTokenHandler.CreateToken(userName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,16 +29,17 @@ namespace Bootstrap.Admin.Controllers.Api
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onlineUserSvr"></param>
|
/// <param name="onlineUserSvr"></param>
|
||||||
|
/// <param name="ipLocator"></param>
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public bool Post([FromServices]IOnlineUsers onlineUserSvr, [FromBody]Log value)
|
public bool Post([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, [FromBody]Log value)
|
||||||
{
|
{
|
||||||
var agent = new UserAgent(Request.Headers["User-Agent"]);
|
var agent = new UserAgent(Request.Headers["User-Agent"]);
|
||||||
value.Ip = (HttpContext.Connection.RemoteIpAddress ?? IPAddress.IPv6Loopback).ToString();
|
value.Ip = (HttpContext.Connection.RemoteIpAddress ?? IPAddress.IPv6Loopback).ToString();
|
||||||
value.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
value.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
||||||
value.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
value.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
||||||
value.City = onlineUserSvr.RetrieveLocaleByIp(value.Ip);
|
value.City = ipLocator.Locate(value.Ip);
|
||||||
value.UserName = User.Identity.Name;
|
value.UserName = User.Identity.Name;
|
||||||
return LogHelper.Save(value);
|
return LogHelper.Save(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Longbow.Web;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System;
|
using System;
|
||||||
|
|
|
@ -1,187 +0,0 @@
|
||||||
using Bootstrap.DataAccess;
|
|
||||||
using Longbow.Cache;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Bootstrap.Admin
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
internal class DefaultOnlineUsers : IOnlineUsers
|
|
||||||
{
|
|
||||||
private readonly ConcurrentDictionary<string, AutoExpireCacheEntry<OnlineUser>> _onlineUsers = new ConcurrentDictionary<string, AutoExpireCacheEntry<OnlineUser>>();
|
|
||||||
private readonly ConcurrentDictionary<string, AutoExpireCacheEntry<string>> _ipLocator = new ConcurrentDictionary<string, AutoExpireCacheEntry<string>>();
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private readonly IEnumerable<string> _local = new string[] { "::1", "127.0.0.1" };
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="factory"></param>
|
|
||||||
public DefaultOnlineUsers(IHttpClientFactory factory)
|
|
||||||
{
|
|
||||||
_client = factory.CreateClient(OnlineUsersServicesCollectionExtensions.IPSvrHttpClientName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public IEnumerable<OnlineUser> OnlineUsers
|
|
||||||
{
|
|
||||||
get { return _onlineUsers.Values.Select(v => v.Value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="addValueFactory"></param>
|
|
||||||
/// <param name="updateValueFactory"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
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>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="onlineUserCache"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool TryRemove(string key, out AutoExpireCacheEntry<OnlineUser> onlineUserCache) => _onlineUsers.TryRemove(key, out onlineUserCache);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ip"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
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();
|
|
||||||
if (ipSvr.IsNullOrEmpty() || ipSvr.Equals("None", StringComparison.OrdinalIgnoreCase) || ip.IsNullOrEmpty() || _local.Any(p => p == ip)) return "本地连接";
|
|
||||||
|
|
||||||
var ipSvrUrl = DictHelper.RetrieveLocaleIPSvrUrl(ipSvr);
|
|
||||||
if (ipSvrUrl.IsNullOrEmpty()) return "本地连接";
|
|
||||||
|
|
||||||
var url = $"{ipSvrUrl}{ip}";
|
|
||||||
var task = ipSvr == "BaiDuIPSvr" ? RetrieveLocator<BaiDuIPLocator>(url) : RetrieveLocator<JuheIPLocator>(url);
|
|
||||||
task.Wait();
|
|
||||||
return task.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<string> RetrieveLocator<T>(string url)
|
|
||||||
{
|
|
||||||
var ret = default(T);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ret = await _client.GetAsJsonAsync<T>(url);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
ex.Log(new NameValueCollection()
|
|
||||||
{
|
|
||||||
["Url"] = url
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return ret?.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
private class BaiDuIPLocator
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 详细地址信息
|
|
||||||
/// </summary>
|
|
||||||
public string Address { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 结果状态返回码
|
|
||||||
/// </summary>
|
|
||||||
public string Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Status == "0" ? string.Join(" ", Address.SpanSplit("|").Skip(1).Take(2)) : "XX XX";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class JuheIPLocator
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ResultCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Reason { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public JuheIPLocatorResult Result { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <value></value>
|
|
||||||
public int Error_Code { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Error_Code != 0 ? "XX XX" : Result.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class JuheIPLocatorResult
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Country { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Province { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string City { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Isp { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Country != "中国" ? $"{Country} {Province} {Isp}" : $"{Province} {City} {Isp}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
using Longbow.Cache;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Bootstrap.Admin
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public interface IOnlineUsers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
IEnumerable<OnlineUser> OnlineUsers { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="addValueFactory"></param>
|
|
||||||
/// <param name="updateValueFactory"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
AutoExpireCacheEntry<OnlineUser> AddOrUpdate(string key, Func<string, AutoExpireCacheEntry<OnlineUser>> addValueFactory, Func<string, AutoExpireCacheEntry<OnlineUser>, AutoExpireCacheEntry<OnlineUser>> updateValueFactory);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="onlineUserCache"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
bool TryRemove(string key, out AutoExpireCacheEntry<OnlineUser> onlineUserCache);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ip"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
string RetrieveLocaleByIp(string ip = null);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Bootstrap.Admin
|
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class OnlineUser
|
|
||||||
{
|
|
||||||
private ConcurrentQueue<KeyValuePair<DateTime, string>> _requestUrls = new ConcurrentQueue<KeyValuePair<DateTime, string>>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ConnectionId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string UserName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime FirstAccessTime { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime LastAccessTime { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Location { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Method { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Ip { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Browser { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string OS { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string RequestUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<KeyValuePair<DateTime, string>> RequestUrls
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _requestUrls.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="url"></param>
|
|
||||||
public void AddRequestUrl(string url)
|
|
||||||
{
|
|
||||||
_requestUrls.Enqueue(new KeyValuePair<DateTime, string>(DateTime.Now, url));
|
|
||||||
if (_requestUrls.Count > 5)
|
|
||||||
{
|
|
||||||
_requestUrls.TryDequeue(out _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
using Bootstrap.Admin;
|
|
||||||
using Bootstrap.DataAccess;
|
|
||||||
using Longbow.Cache;
|
|
||||||
using Longbow.Web;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Builder
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class OnlineUsersMiddlewareExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="builder"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static IApplicationBuilder UseOnlineUsers(this IApplicationBuilder builder) => builder.UseWhen(context => context.Filter(), app => app.Use(async (context, next) =>
|
|
||||||
{
|
|
||||||
await System.Threading.Tasks.Task.Run(() =>
|
|
||||||
{
|
|
||||||
var user = UserHelper.RetrieveUserByUserName(context.User.Identity.Name);
|
|
||||||
if (user == null) return;
|
|
||||||
|
|
||||||
var onlineUserSvr = context.RequestServices.GetRequiredService<IOnlineUsers>();
|
|
||||||
var proxy = new Func<AutoExpireCacheEntry<OnlineUser>, Action, AutoExpireCacheEntry<OnlineUser>>((c, action) =>
|
|
||||||
{
|
|
||||||
var v = c.Value;
|
|
||||||
v.UserName = user.UserName;
|
|
||||||
v.DisplayName = user.DisplayName;
|
|
||||||
v.LastAccessTime = DateTime.Now;
|
|
||||||
v.Method = context.Request.Method;
|
|
||||||
v.RequestUrl = context.Request.Path;
|
|
||||||
v.AddRequestUrl(context.Request.Path);
|
|
||||||
action?.Invoke();
|
|
||||||
TraceHelper.Save(new Trace { Ip = v.Ip, RequestUrl = v.RequestUrl, LogTime = v.LastAccessTime, City = v.Location, Browser = v.Browser, OS = v.OS, UserName = v.UserName });
|
|
||||||
return c;
|
|
||||||
});
|
|
||||||
onlineUserSvr.AddOrUpdate(context.Connection.Id ?? "", key =>
|
|
||||||
{
|
|
||||||
var agent = new UserAgent(context.Request.Headers["User-Agent"]);
|
|
||||||
var v = new OnlineUser();
|
|
||||||
v.ConnectionId = key;
|
|
||||||
v.Ip = (context.Connection.RemoteIpAddress ?? IPAddress.IPv6Loopback).ToString();
|
|
||||||
v.Location = onlineUserSvr.RetrieveLocaleByIp(v.Ip);
|
|
||||||
v.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
|
||||||
v.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
|
||||||
v.FirstAccessTime = DateTime.Now;
|
|
||||||
return proxy(new AutoExpireCacheEntry<OnlineUser>(v, 1000 * 60, __ => onlineUserSvr.TryRemove(key, out _)), null);
|
|
||||||
}, (key, v) => proxy(v, () => v.Reset()));
|
|
||||||
});
|
|
||||||
await next();
|
|
||||||
}));
|
|
||||||
|
|
||||||
private static bool Filter(this HttpContext context)
|
|
||||||
{
|
|
||||||
var url = context.Request.Path;
|
|
||||||
return !new string[] { "/api", "/NotiHub", "/swagger" }.Any(r => url.StartsWithSegments(r, StringComparison.OrdinalIgnoreCase));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
using Bootstrap.Admin;
|
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.DependencyInjection
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class OnlineUsersServicesCollectionExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
internal const string IPSvrHttpClientName = "IPSvr";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="services"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static IServiceCollection AddOnlineUsers(this IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.TryAddSingleton<IOnlineUsers, DefaultOnlineUsers>();
|
|
||||||
services.AddHttpClient(IPSvrHttpClientName, client =>
|
|
||||||
{
|
|
||||||
client.DefaultRequestHeaders.Connection.Add("keep-alive");
|
|
||||||
});
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Bootstrap.DataAccess;
|
using Bootstrap.DataAccess;
|
||||||
using Bootstrap.Security.Filter;
|
using Bootstrap.Security.Filter;
|
||||||
using Longbow.Web;
|
using Longbow.Web;
|
||||||
using Longbow.Web.SignalR;
|
using Longbow.Web.SignalR;
|
||||||
|
@ -60,6 +60,7 @@ namespace Bootstrap.Admin
|
||||||
services.AddConfigurationManager(Configuration);
|
services.AddConfigurationManager(Configuration);
|
||||||
services.AddCacheManager(Configuration);
|
services.AddCacheManager(Configuration);
|
||||||
services.AddDbAdapter();
|
services.AddDbAdapter();
|
||||||
|
services.AddIPLocator(DictHelper.ConfigIPLocator);
|
||||||
services.AddOnlineUsers();
|
services.AddOnlineUsers();
|
||||||
var dataProtectionBuilder = services.AddDataProtection(op => op.ApplicationDiscriminator = Configuration["ApplicationDiscriminator"])
|
var dataProtectionBuilder = services.AddDataProtection(op => op.ApplicationDiscriminator = Configuration["ApplicationDiscriminator"])
|
||||||
.SetApplicationName(Configuration["ApplicationName"])
|
.SetApplicationName(Configuration["ApplicationName"])
|
||||||
|
@ -127,7 +128,7 @@ namespace Bootstrap.Admin
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseBootstrapAdminAuthorization(RoleHelper.RetrieveRolesByUserName, RoleHelper.RetrieveRolesByUrl, AppHelper.RetrievesByUserName);
|
app.UseBootstrapAdminAuthorization(RoleHelper.RetrieveRolesByUserName, RoleHelper.RetrieveRolesByUrl, AppHelper.RetrievesByUserName);
|
||||||
app.UseOnlineUsers();
|
app.UseOnlineUsers(callback: TraceHelper.Save);
|
||||||
app.UseCacheManagerCorsHandler();
|
app.UseCacheManagerCorsHandler();
|
||||||
app.UseSignalR(routes => { routes.MapHub<SignalRHub>("/NotiHub"); });
|
app.UseSignalR(routes => { routes.MapHub<SignalRHub>("/NotiHub"); });
|
||||||
app.UseMvc(routes =>
|
app.UseMvc(routes =>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<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.5" />
|
<PackageReference Include="Longbow.Cache" Version="2.2.5" />
|
||||||
<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.9" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.1.0" />
|
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.1.0" />
|
||||||
<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.9" />
|
||||||
<PackageReference Include="Longbow.Cache" Version="2.2.5" />
|
<PackageReference Include="Longbow.Cache" Version="2.2.5" />
|
||||||
<PackageReference Include="Longbow" Version="2.2.8" />
|
<PackageReference Include="Longbow" Version="2.2.8" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using Bootstrap.Security;
|
using Bootstrap.Security;
|
||||||
using Longbow.Cache;
|
using Longbow.Cache;
|
||||||
using Longbow.Data;
|
using Longbow.Data;
|
||||||
|
using Longbow.Web;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
@ -75,6 +77,21 @@ namespace Bootstrap.DataAccess
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="op"></param>
|
||||||
|
public static void ConfigIPLocator(IPLocatorOption op)
|
||||||
|
{
|
||||||
|
var name = RetrieveLocaleIPSvr();
|
||||||
|
if (!string.IsNullOrEmpty(name) && !name.Equals("None", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var url = RetrieveLocaleIPSvrUrl(name);
|
||||||
|
op.Locator = string.IsNullOrEmpty(url) ? null : DefaultIPLocatorProvider.CreateLocator(name);
|
||||||
|
op.Url = string.IsNullOrEmpty(url) ? string.Empty : $"{url}{op.IP}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存网站个性化设置
|
/// 保存网站个性化设置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using Longbow.Data;
|
using Longbow.Data;
|
||||||
|
using Longbow.Web;
|
||||||
using Longbow.Web.Mvc;
|
using Longbow.Web.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using PetaPoco;
|
using PetaPoco;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
@ -11,8 +13,27 @@ namespace Bootstrap.DataAccess
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存访问历史记录
|
/// 保存访问历史记录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="p"></param>
|
/// <param name="context"></param>
|
||||||
public static void Save(Trace p) => DbContextManager.Create<Trace>().Save(p);
|
/// <param name="v"></param>
|
||||||
|
public static void Save(HttpContext context, OnlineUser v)
|
||||||
|
{
|
||||||
|
if (context.User.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
var user = UserHelper.RetrieveUserByUserName(context.User.Identity.Name);
|
||||||
|
v.UserName = user.UserName;
|
||||||
|
v.DisplayName = user.DisplayName;
|
||||||
|
DbContextManager.Create<Trace>().Save(new Trace
|
||||||
|
{
|
||||||
|
Ip = v.Ip,
|
||||||
|
RequestUrl = v.RequestUrl,
|
||||||
|
LogTime = v.LastAccessTime,
|
||||||
|
City = v.Location,
|
||||||
|
Browser = v.Browser,
|
||||||
|
OS = v.OS,
|
||||||
|
UserName = v.UserName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得指定IP历史访问记录
|
/// 获得指定IP历史访问记录
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using Longbow.Web;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
using Bootstrap.DataAccess;
|
using Bootstrap.DataAccess;
|
||||||
using Longbow.Data;
|
|
||||||
using Longbow.Web.Mvc;
|
using Longbow.Web.Mvc;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using DbManager = Longbow.Data.DbManager;
|
|
||||||
|
|
||||||
namespace Bootstrap.Admin.Api
|
namespace Bootstrap.Admin.Api
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue