我正在使用c#和asp.net为我的网站创建一个论坛系统,对于数据访问,我使用的是类型化数据集,对于UI,我正在使用mvp模式。 在我的数据库中,我有存储过程,我已添加到我的数据集中。 问题是数据集不允许我选择“使用乐观并发”复选框,所以我必须自己实现乐观并发。 我已经为我的表添加了一个时间戳列,现在我遇到了为每个用户保存此值的问题! 那么什么状态管理方法是安全的,并且用于保存时间戳值的成本更低?

我想也许最好使用session来存储值,但是如果用户的数量增加,我会遇到内存资源问题但是我可以设置会话使用sql server而不是内存但我不知道会慢多少所以我无法决定。

任何帮助是赞赏的家伙!

编辑1:是的。 我想跟踪行的最后一次修改,看它是否与用户拥有的那个匹配。 但我不知道在哪里保存用户的时间戳值。

===============>>#1 票数:6 已采纳

如果由于某种原因你不能使用timestamp / rowversion它是一个论坛类型的应用程序我会猜你跟踪发布创建/修改日期/时间? 如果是这样,这将是一件容易检查的事情。

更新

SQL Server模式

SQL Server Mode的用例通常是Web服务器场,因此ASP.NET会话状态在多个服务器上保持不变。 这使得它更加健壮,因为如果Web服务器变得不可用,只要另一个可用,会话就可以正常继续。 SQL Server模式没有本地快,除非资源受到严重的争议,因为我们正在查询数据库而不是同一服务器的内存(进程外)或甚至是同一进程(进程内)。

MVC模式和会话状态

如果您在应用程序中使用WebFormViewEngine,则可以使用state,但MVC模式的主要租户是无状态的。

如何跟踪rowversion / timestamp无状态

为了以无状态方式跟踪rowversion,我们需要将它返回给客户端,因此当回调到控制器动作时,它就是为我们提供的。

<%= Html.HiddenFor(Model.VersionId) %>

这将导致生成的HTML表单中的隐藏字段。

<input type="hidden" name="VersionId">1</input> 

安全吗?

将此临时存储在客户端上是否安全,完全知道可能有人可能会在攻击您的Web应用程序时改变该值。

让我们分析一下我们所知道的:

  • Microsoft不建议手动增加它以防止在同一个表中重复相同的rowversion。
  • 每个表插入/更新按顺序递增,而不是按记录递增。 即,记录A可以具有版本1记录B可以具有版本2.记录A的下一次更新将使其为3而不是2.请参阅http://msdn.microsoft.com/en-us/library/ms182776.aspx

基于此,我们将编写我们的应用程序以使用rowversion,以便我们使用rowversion来确定记录是否在我们当前请求的更新之间发生了变化。 我们将始终让DB在内部增加rowversion。 因此,存储过程将接受该值以进行比较,但不在表/视图中插入或更新它。

那么如果有人试图操纵它,那么rowversion可能会出现什么情况。

  1. 客户端提供的rowversion小于DB的rowversion。
  2. 客户端提供的rowversion等于DB的rowversion。
  3. 客户端提供的rowversion大于DB的rowversion。

让我们打破这一点。

那么如果客户端rowversion小于DB那意味着什么呢?

客户端在编辑数据时使用了旧数据副本,因为自上次从数据库读取数据后,客户端已经发生了更改。 为了解决这个问题,我们可以:

A.给他们一个错误,重新加载数据并让他们重新提交他们的更改。

B.将他们的更改合并到当前副本中,并在重新提交之前要求确认。

C.覆盖DB中的现有副本。 好吧,我们可以做到这一点,但由于我们实现了一个并发模型来同时处理多个更改,它可能不是最合适的。 这给我们留下了A和B.

另一个选项是客户端将rowversion的值更改为小于实际的DB值。 在这种情况下,即使他们确实改变了rowversion的价值,这也很重要吗? 我建议它不会,并且应该像处理与另一个用户同时更改一样处理。 再次返回选项A和B.

因此,如果客户端rowversion等于DB,那意味着什么?

客户端正在编辑他们期望的版本并点击提交按钮。 为了解决这个问题,我们可以:

A.接受他们的更改并继续。

B.拒绝更改并提供反馈消息。 我们不太可能想要这样做,因为它总是将数据输入数据库。

另一个选择是客户端将rowversion的值更改为我们期望的正确版本,或者很可能根本没有修改它,因为我们告诉他们我们所期望的rowversion与我们为所有提交做的一样。 但是,如果他们确实改变了rowversion,并且同时发布了他们的更新客户端,这是要提交的最后一次更新。

我们可以像A或B之前那样处理这种情况。不幸的是,我们无法知道它们实际上修改了rowversion,因为它符合预期。 但是我们已经允许他们对记录进行更新。 如果他们不应该更新记录,那么他们就没有权限这样做。

也就是说,在将其写入数据库之前,我们仍将验证所有输入的完整性并对其进行消毒。

如果这不好,那么我们需要在我们的应用程序中实现内容版本控制或批准过程,以便在我们更新每条记录或允许回滚到先前版本之前让我们控制。

因此,如果客户端rowversion大于DB,这意味着什么?

那么选项与rowversion小于DB的情况完全相同。 这不是预期的,所以A或B.再次C可能不是一个选项,因为它击败了目的。

结论

那么论坛Web应用程序是否安全? 我们仍然需要验证输入,但如果rowversion与预期不同,我们有解决方法。

作为最后的手段,我们还可以对rowversion进行编码或加密,以防止序列被轻易猜到。

所以在我看来是的,但这最终是你的号召。

  ask by jim translate from so

未解决问题?本站智能推荐:

1回复

交易范围和乐观并发

我想对TransactionScope使用乐观并发。 到目前为止,这是我提出的代码: 不幸的是,这段代码有一个严重的问题。 在版本检查和事务提交之间,数据库中可能会有一些更改。 这是检查使用时间错误的标准时间 。 我可以看到解决此问题的唯一方法是将版本检查和事务提交作为单个命令执
4回复

使用乐观并发方法处理多个生产者插入唯一“不可变”实体的有效方法是什么?

假设一个具有多个并发生成器的系统,每个生成器都努力使用以下可通过其名称唯一标识的公共实体来持久保存一些对象图: 例如,生产者A保存了一些CommonEntityMeeting ,而生产者B保存了CommonEntitySet 。 他们中的任何一个都必须坚持与其特定项目相关的Common
1回复

通过并发检查SQL Server升级

由于使用量增加和出现了一些问题,我的生产系统需要对并发检查进行改进。 目前,我正在使用遵循基本upsert模式的存储过程: 进入这种混合中,我需要检查行更改。 我计划使用Rowversion / Timestamp。 我不想只添加: 我想触发一个SQL错误或C#可能
1回复

需要进行乐观并发交易吗?

仔细阅读此问题后,有几处提到乐观并发由于中止交易而在解决过程中的代价更高: 乐观锁定与悲观锁定 如果要执行单个update语句,通常会制作where子句以确保如果冲突则不进行任何更新。 也就是说,您将在where子句中包含原始行状态。 如果其他人编辑了该行并且发生冲突,由于whe
3回复

数据集乐观并发

我需要在我的数据集C#客户端中做什么来处理乐观并发? 本文除了使用时间戳之外,没有涉及太多细节
1回复

乐观并发处理-Asp.Net WebApi Odata V4

这是我的OdataController的Patch方法 我的模型有一个属性: DbUpdateConcurrencyException似乎根本不起作用。 我需要使用Etag实现并发检查机制。 我在这里看到了一些示例。但是他们没有在其中使用Delta方法。 如何使用e
3回复

使用SqlDataSource删除空字典错误 - ASP.net ListView

我正在尝试使用乐观并发创建一个简单的ListView。 它使用VS自动生成的Delete,Insert,Update语句(除了1更改插入:参见代码)。 插入和编辑工作正常并提交到数据库。 尝试删除时,我收到此错误: 您已指定delete命令比较SqlDataSource'MySour
1回复

如何避免EF中新添加记录的乐观并发错误

我在MVC 5项目中使用Entity Framework 6,在Experiment和FileAttachment之间存在实体关系(一个Experiment可以提供多个FileAttachment)。 在“编辑实验”记录期间,我加载了一个包含两个实体的ViewModel并在编辑模式下列出了该实
1回复

使用NHibernate(和Fluent NH)映射日期时间类型版本列的精度高于第二精度(而不是截断毫秒)

我有一个datetime类型列的表作为版本。 它是一个遗留数据库,因此我无法将其更改为datetime2或使用不同的版本控制机制。 NHibernate类将其映射到DateTime c#typed属性。 我已经看过几个问题以及有关此问题的论坛帖子和回复,但无论我尝试过什么,NHiber
1回复

意外的乐观并发异常

我尝试更新对象的字段,并将其立即保存到数据库中。 当我在具有2个或更多实例的Azure模拟器中运行此代码时,在这里会出现很多OptimisticConcurrencyExceptions。 我正在尝试刷新对象,更新其字段之一,然后将这些更改推送到数据库。 但是,乐观并发阻止了我。