2019-03-17 19:37:15 +08:00
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
2019-03-01 02:00:47 +08:00
|
|
|
|
using System;
|
2019-03-17 19:37:15 +08:00
|
|
|
|
using System.Collections.Concurrent;
|
2019-02-28 16:44:50 +08:00
|
|
|
|
using System.Collections.Generic;
|
2019-03-01 02:00:47 +08:00
|
|
|
|
using System.Linq;
|
2019-03-17 19:37:15 +08:00
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
|
2019-02-28 16:44:50 +08:00
|
|
|
|
namespace Bootstrap.Admin.Controllers.Api
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
2019-03-01 02:00:47 +08:00
|
|
|
|
/// 在线用户接口
|
2019-02-28 16:44:50 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
[Route("api/[controller]")]
|
|
|
|
|
[ApiController]
|
|
|
|
|
public class OnlineUsersController : ControllerBase
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
2019-03-01 02:00:47 +08:00
|
|
|
|
/// 获取所有在线用户数据
|
2019-02-28 16:44:50 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpPost()]
|
|
|
|
|
public IEnumerable<OnlineUser> Post([FromServices]IOnlineUsers onlineUSers)
|
|
|
|
|
{
|
2019-03-02 15:15:47 +08:00
|
|
|
|
return onlineUSers.OnlineUsers.OrderByDescending(u => u.LastAccessTime);
|
2019-02-28 16:44:50 +08:00
|
|
|
|
}
|
2019-03-01 02:00:47 +08:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
2019-03-02 15:15:47 +08:00
|
|
|
|
/// 获取指定会话的在线用户请求地址明细数据
|
2019-03-01 02:00:47 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id"></param>
|
|
|
|
|
/// <param name="onlineUSers"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpGet("{id}")]
|
|
|
|
|
public IEnumerable<KeyValuePair<DateTime, string>> Get(string id, [FromServices]IOnlineUsers onlineUSers)
|
|
|
|
|
{
|
2019-03-02 15:15:47 +08:00
|
|
|
|
var user = onlineUSers.OnlineUsers.FirstOrDefault(u => u.ConnectionId == id);
|
2019-03-01 02:00:47 +08:00
|
|
|
|
return user?.RequestUrls ?? new KeyValuePair<DateTime, string>[0];
|
|
|
|
|
}
|
2019-03-17 19:37:15 +08:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 登录页面检查调用
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>返回真时 启用行为验证码</returns>
|
|
|
|
|
[HttpPut]
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public bool Put()
|
|
|
|
|
{
|
|
|
|
|
var ip = (Request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.IPv6Loopback).ToString();
|
|
|
|
|
if (_loginUsers.TryGetValue(ip, out var user))
|
|
|
|
|
{
|
|
|
|
|
user.Reset();
|
|
|
|
|
user.User.Count++;
|
|
|
|
|
return user.User.Count > 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var loginUser = new LoginUser() { Ip = ip };
|
|
|
|
|
_loginUsers.TryAdd(ip, new LoginUserCache(loginUser, () => _loginUsers.TryRemove(ip, out _)));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static ConcurrentDictionary<string, LoginUserCache> _loginUsers = new ConcurrentDictionary<string, LoginUserCache>();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
///
|
|
|
|
|
/// </summary>
|
|
|
|
|
private class LoginUser
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
///
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string Ip { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
///
|
|
|
|
|
/// </summary>
|
|
|
|
|
public int Count { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
///
|
|
|
|
|
/// </summary>
|
|
|
|
|
private class LoginUserCache : IDisposable
|
|
|
|
|
{
|
|
|
|
|
private Timer dispatcher;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
///
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="user"></param>
|
|
|
|
|
/// <param name="action"></param>
|
|
|
|
|
public LoginUserCache(LoginUser user, Action action)
|
|
|
|
|
{
|
|
|
|
|
User = user;
|
|
|
|
|
dispatcher = new Timer(_ => action(), null, TimeSpan.FromSeconds(30), Timeout.InfiniteTimeSpan);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
///
|
|
|
|
|
/// </summary>
|
|
|
|
|
public LoginUser User { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
///
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void Reset()
|
|
|
|
|
{
|
|
|
|
|
if (dispatcher != null) dispatcher.Change(TimeSpan.FromSeconds(30), 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
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-02-28 16:44:50 +08:00
|
|
|
|
}
|