「所有」するエンティティStoreOwner
があるか、Store
エンティティと@OneToMany
の関係にあるサーバーを書いています(1人の店主が1からNの店を持っています)。各Store
にはOffer
とItem
があり、各ストアとも@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
に移動することもできますが、もっと良いオプションはありますか?
これはアクセス制御と呼ばれます。
操作を実行する前に、ユーザーがレコードにアクセスできることを確認する必要があります。
最も簡単な方法は、テナントごとに異なるデータベースまたはスキーマを使用することです。または...
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
親テーブルへの外部キー。