如何将脆弱的数据例如连接字符串从一个控制器传递到另一个控制器

How to pass fragile data e.g connection string from one controller to another

我是 asp.net 核心的新手,我正在尝试开发一个在线 SQL 数据库管理器,它可以在任何 SQL 数据库上运行,通过后:ServerAddress、Login、Password和 DatabaseType(我的 ConnectionInformation 模型)。

类似于 SSMS,但在线。

我想将我的 ConnectionInformation 模型从登录控制器传递到数据库控制器。

重定向到操作使用公开我所有数据的查询字符串。 TempData 只接受字符串,将我的模型转换为 json 并不是解决此问题的最优雅方法。

登录控制器:

public class LoginController : Controller
{
    private readonly ILoginLogic _loginLogic;

    public LoginController(ILoginLogic loginLogic)
    {
        _loginLogic = loginLogic;
    }

    [HttpGet]
    public IActionResult Index()
    {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Index(ConnectionInformationViewModel connectionViewModel)
    {
        if (!ModelState.IsValid)
            return View();

        ConnectionInformation connection = Mapper.Mapper.ConnectionInformationMapper(connectionViewModel);

        var connectionSuccess = _loginLogic.ConnectToDatabase(connection);

        if (connectionSuccess)
            return RedirectToAction("Index", "Database", connection);
        else
            return View(); // TODO: Return view with error or handle it in js
    }
}

数据库控制器:

 public class DatabaseController : Controller
    {
        private readonly IDatabaseLogic _databaseLogic;

        public DatabaseController(IDatabaseLogic databaseLogic)
        {
            _databaseLogic = databaseLogic;
        }

        public IActionResult Index(ConnectionInformation connection)
        {
            var databases = _databaseLogic.GetDatabases(connection);
            return View(databases);
        }
    }

也许我的做法是完全错误的。我的主要目标是检查我是否可以连接到数据库,如果可以,我想对该数据库执行查询操作,直到用户注销。

嗯,很简单,您必须以某种方式保留信息。在这方面,有多种选择。您可以将其保存在客户端的本地存储中,并在每次进一步请求时实际将其传回。不过,这对于 SPA 风格的应用程序效果更好,您几乎可以通过 AJAX 完成所有操作。另一种技术上的客户端存储机制是使用 posted 连接信息设置会话 cookie。在这里,我谈论的是显式设置和读取具有 "session" 生命周期的 cookie,而不是使用会话。

或者您实际上可以使用真正的会话,即 SessionTempData 基本上只是 Session 无论如何,但在这里它是不合适的,因为你需要确保每次访问时都保留 TempData 否则它将无法在下一次访问时继续存在要求。如果你这样做,那么你最好使用 Session 而不必担心它。

无论你做什么,序列化都是必不可少的。没有办法持久化实际的 C# 对象实例,因此您要么必须将其写入数据库等关系存储,要么将其序列化为 JSON.

另一种避免必须保留实际连接信息的替代解决方案是基本上创建您自己的连接池。这将需要一个单例范围的 class 和一个 ConcurrentDictionary ivar,并且可能使用 SemaphoreSlim 在该字典的读写过程中进行锁定,这样您就不会创建和孤立连接。然后,您只需要以某种方式将密钥分配给字典客户端中的特定连接,例如通过 Session 或 cookie。这实际上也更安全一些,因为您不会保留超过初始 post 的数据库连接信息,但如果并发用户太多,您可能最终会耗尽可用的服务器连接。当然,无论如何这都可能成为一个问题。您还需要一些用于驱逐连接的策略。这不是最简单的设置。

就我个人而言,我只是坚持在这个上使用 Session。只要采取标准的会话劫持预防措施,它就足够安全,而且实施起来也很简单。如果你正在构建一个 SPA 风格的应用程序,那么我会坚持使用本地存储,因为这将更好地保持信息客户端开始,但它需要更多的管道。