BankProject/Server/SessionManager.cs
GabrielTofvesson 98a6557000 Fixed some issues with asynchronous code
Updated some old code to use new methods
ECDH implementation now uses BitWriter/BitReader to serialize/deserialize
Added error handling to NetClient for predictable cases of error
Fixed regular SHA1 implementation
Partially remade optimized SHA1 implementation as a hybrid implementation between minimum allocation and minimum processor overhead
Fixed how Databse manages serialization/deserialization of Users
Updated Output class to support any type
Output now supports overwritable lines
Added OutputFormatter to simplify creating-column output
Sessions keys are no longer invalidated when client-server connection is closed
Added command system to server for easier administration
2018-04-26 23:51:41 +02:00

131 lines
3.7 KiB
C#

using System;
using System.Collections.Generic;
using Tofvesson.Crypto;
namespace Server
{
public sealed class SessionManager
{
private static readonly RandomProvider random = new RegularRandomProvider();
private readonly List<Session> sessions = new List<Session>();
private readonly long timeout;
private readonly int sidLength;
public List<Session> Sessions { get => sessions; }
public SessionManager(long timeout, int sidLength = 10)
{
this.timeout = timeout;
this.sidLength = sidLength < 10 ? 10 : sidLength;
}
public string GetSession(Database.User user, string invalidSID)
{
Update();
for (int i = 0; i < sessions.Count; ++i)
if (sessions[i].user.Equals(user))
return sessions[i].sessionID;
Session s = new Session
{
sessionID = GenerateRandomSID(invalidSID),
user = user,
expiry = DateTime.Now.Ticks + timeout
};
sessions.Add(s);
return s.sessionID;
}
public Database.User GetUser(string SID)
{
foreach (var session in sessions)
if (session.sessionID.Equals(SID))
return session.user;
return null;
}
public bool Refresh(Database.User user)
{
Update();
for (int i = sessions.Count - 1; i >= 0; --i)
if (sessions[i].user.Equals(user))
{
Session s = sessions[i];
s.expiry = DateTime.Now.Ticks + timeout;
sessions[i] = s;
return true;
}
return false;
}
public void Expire(Database.User user)
{
Update();
for (int i = sessions.Count - 1; i >= 0; --i)
if (sessions[i].user.Equals(user))
{
sessions.RemoveAt(i);
return;
}
return;
}
public bool Refresh(string sid)
{
Update();
for (int i = sessions.Count - 1; i >= 0; --i)
if (sessions[i].sessionID.Equals(sid))
{
Session s = sessions[i];
s.expiry = DateTime.Now.Ticks + timeout;
sessions[i] = s;
return true;
}
return false;
}
public bool Expire(string sid)
{
Update();
for (int i = sessions.Count - 1; i >= 0; --i)
if (sessions[i].sessionID.Equals(sid))
{
sessions.RemoveAt(i);
return true;
}
return false;
}
public bool CheckSession(string sid, Database.User user)
{
foreach (var session in sessions)
if (session.sessionID.Equals(sid) && session.user.Equals(user))
return true;
return false;
}
public void Update()
{
for(int i = sessions.Count - 1; i>=0; --i)
if (sessions[i].expiry < DateTime.Now.Ticks)
sessions.RemoveAt(i);
}
private string GenerateRandomSID(string invalid)
{
string res;
do res = random.NextString(sidLength);
while (res.StartsWith(invalid));
return res;
}
}
public struct Session
{
public string sessionID;
public Database.User user;
public long expiry; // Measured in ticks
}
}