web-dev-qa-db-ja.com

ユーザーが所有していないリソースを変更できないようにするにはどうすればよいですか?

「所有」するエンティティStoreOwnerがあるか、Storeエンティティと@OneToManyの関係にあるサーバーを書いています(1人の店主が1からNの店を持っています)。各StoreにはOfferItemがあり、各ストアとも@OneToManyの関係にあります(1つのストアには1対Nのオファーと1対Nのアイテムがあります)。

私はすでにGWT Xsrf保護を使用していますおよび各ログイン(Cookie)の後にログインしたユーザーに関連付けられるセッションID。

IMHOに欠けていることが1つあります。ログインしているユーザーがdeleteリクエストを、自分が所有していないストアのアイテムの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;
}

より大きなサーバーアプリケーションを作成しようとしているのは初めてであり、ユーザーがそのようなことをするのを防ぎたいのです。

私の質問は2つあります:[1]私がしていることは、ログインしているユーザーが自分が所有していない別のストアのIDを私のサーバーに密輸することを本当に妨げますか?さらに、[2]これを少し簡略化できますか?

私の問題は、アプリケーションが成長するにつれて、時々-このチェックを忘れることです

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

もちろん、それをStoreOwnerRepositoryに移動することもできますが、もっと良いオプションはありますか?

11
displayname

これはアクセス制御と呼ばれます。

操作を実行する前に、ユーザーがレコードにアクセスできることを確認する必要があります。

最も簡単な方法は、テナントごとに異なるデータベースまたはスキーマを使用することです。または...

Javaを使用する場合、Spring Securityを使用できます。これは、Spring Data JPAで integrates になり、SQLクエリにuserid/usernameを簡単に渡すことができます。

または、データベースで行セキュリティ権限を使用します。 Oracleに1000万ドルの余裕がある場合は、10月にPostgreSQLで利用可能になります。 更新可能なsecurity_barrier CHECK OPTIONビューでそれを模倣する PG 9.4以降。このためには、 WebサーバーがDBサーバーに通知する 現在のユーザーの名前を指定する必要があります。

おそらくowner_id列を「子」テーブルに追加します。 on update cascade親テーブルへの外部キー。

12
Neil McGuigan