如何防止用户修改他们不拥有的资源?

信息安全 Web应用程序 网络服务器
2021-08-24 22:00:30

我正在编写一个服务器,其中我有一个实体StoreOwner“拥有”或@OneToMany与一个实体有关系Store(一个店主有 1 到 N 家商店)。每个Store都有OfferItem,每个也@OneToMany与商店有关系(一个商店有 1 到 N 个优惠和 1 到 N 个商品)。

我已经在使用 GWT Xsrf 保护在每次登录后与登录用户关联的会话 ID (cookie)。

恕我直言,缺少一件事:如果登录用户向服务器发送删除请求,其中包含他不拥有的商店的物品 ID,他也不拥有?目前,我在我的StoreService

// StoreService.java

@Transactional
public ItemDTO deleteItem(String sessionId, Long storeId, ItemDTO itemDto) {

    // sessionId is the cookie I have placed in my database
    // This way I want to ensure that I am only accessing a store
    // that is associated with the logged in store owner (the user basically)
    Store store = this.storeOwnerRepository.getStore(sessionId, storeId);

    Item item = ConvertDTO.convertItem(store, itemDto);

    // Check if the store ID that I got using the cookie is the
    // same ID as the store ID from the item that should be deleted
    if(item .getStore().getId() == store.getId()) {
        item = this.storeOwnerRepository.deleteItem(item);
    } else {
        // If this didn't work we have a potentially hostile user:
        throw new RuntimeException("Is somebody trying to delete items of a store he doesn't own?");
    }

    itemDto = ConvertEntity.convertItem(item);
    return itemDto;
}

这是我第一次尝试编写更大的服务器应用程序,我想阻止用户做这样的事情。

我的问题是双重的:[1] 我正在做的事情真的会阻止登录用户将他不拥有的另一家商店的 ID 走私到我的服务器吗?另外,[2]我可以稍微简化一下吗?

我的问题是,随着应用程序的增长,有时可能会忘记此检查

if(item .getStore().getId() == store.getId()) { /* .. */ }

当然,我可以把它移到我的StoreOwnerRepository中,但是我有更好的选择吗?

1个回答

这称为访问控制。

在对记录执行操作之前,您需要检查用户是否有权访问记录。

最简单的方法是为每个租户使用不同的数据库或模式。或者...

当您使用 Java 时,您可以使用 Spring Security。它现在与 Spring Data JPA集成,允许您轻松地将用户 ID/用户名传递到 SQL 查询中。

或者在数据库中使用 Row Security 权限。如果你有 1000 万美元的闲钱,Oracle 或者这将在 10 月份用于 PostgreSQL。从 PG 9.4 开始,您可以使用可更新的 security_barrier CHECK OPTION 视图模仿它为此,您必须让Web 服务器告诉 db 服务器当前用户的名称。

您可能想在owner_id“子”表中添加一列。对父表使用on update cascade外键。