我找到了一种在服务器端会话中存储用户数据的方法。我使用CircuitHandler Id作为用户访问系统的“令牌”来进行操作。只有用户名和CircuitId被存储在客户端LocalStorage(使用Blazored.LocalStorage);其他用户数据则被保存在服务器上。虽然这需要大量的代码,但这是我找到的最佳方法来保护服务器端的用户数据。
(用于客户端LocalStorage)
public class UserModel
{
public string Username { get; set; }
public string CircuitId { get; set; }
}
SessionModel.cs(我服务器端session的模型)
public class SessionModel
{
public string Username { get; set; }
public string CircuitId { get; set; }
public DateTime DateTimeAdded { get; set; }
public int UserRole { get; set; }
etc...
}
SessionData.cs(保存服务器上所有活跃会话的列表)
public class SessionData
{
private List<SessionModel> sessions = new List<SessionModel>();
private readonly ILogger _logger;
public List<SessionModel> Sessions { get { return sessions; } }
public SessionData(ILogger<SessionData> logger)
{
_logger = logger;
}
public void Add(SessionModel model)
{
model.DateTimeAdded = DateTime.Now;
sessions.Add(model);
_logger.LogInformation("Session created. User:{0}, CircuitId:{1}", model.Username, model.CircuitId);
}
public void Delete(string token)
{
var matchingSession = sessions.FirstOrDefault(s => s.Token == token);
if (matchingSession != null)
{
_logger.LogInformation("Session deleted. User:{0}, Token:{1}", matchingSession.Username, matchingSession.CircuitId);
sessions.RemoveAll(s => s.Token == token);
}
}
public SessionModel Get(string circuitId)
{
return sessions.FirstOrDefault(s => s.CircuitId == circuitId);
}
}
CircuitHandlerService.cs
public class CircuitHandlerService : CircuitHandler
{
public string CircuitId { get; set; }
public SessionData sessionData { get; set; }
public CircuitHandlerService(SessionData sessionData)
{
this.sessionData = sessionData;
}
public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
{
CircuitId = circuit.Id;
return base.OnCircuitOpenedAsync(circuit, cancellationToken);
}
public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
{
sessionData.Delete(circuit.Id);
return base.OnCircuitClosedAsync(circuit, cancellationToken);
}
public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
{
return base.OnConnectionDownAsync(circuit, cancellationToken);
}
public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
{
return base.OnConnectionUpAsync(circuit, cancellationToken);
}
}
Login.razor
@inject ILocalStorageService localStorage
@inject SessionData sessionData
....
public SessionModel session { get; set; } = new SessionModel();
...
if (isUserAuthenticated == true)
{
session.CircuitId = (circuitHandler as CircuitHandlerService).CircuitId;
sessionData.Add(session);
UserModel user = new UserModel
{
Username = session.Username,
CircuitId = session.CircuitId
};
await localStorage.SetItemAsync("userSession", user);
NavigationManager.NavigateTo("Home");
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddServerSideBlazor();
services.AddScoped<CircuitHandler>((sp) => new CircuitHandlerService(sp.GetRequiredService<SessionData>()));
services.AddSingleton<SessionData>();
services.AddBlazoredLocalStorage();
...
}