2016-06-18 9 views
-2

テーブルzを保持カラムa、b、cを持っているといいますか?スプリングMVCと休止状態を確保するためのベストプラクティス

カラムaとbは、許可されたユーザが使用でき、カラムcは管理者だけが使用できます。

私の休止状態エンティティはテーブルzに基づいています。私のスプリングMCUコントローラには、読み込みと書き込みのメソッドがあります。私は春のセキュリティを使用してロールを使用してmvcコントローラを保護することができます。

問題は...(クライアントのフロントエンドがこれを明示的に提供しない場合でも)cの値を設定することで、クライアントがjsonを簡単に設定することですべての列にアクセスできるようになりますオブジェクトを作成し、コントローラwriteメソッドに送信します。また、readメソッドを呼び出すと、c列の値がすべてのユーザーに返されます。

ロールに基づいてそのテーブルにアクセスするとよいでしょうか?

エンティティ:

@Entity 
@Table(name = "hotel") 
@XmlRootElement 
public class Hotel extends BaseEntity implements Serializable { 

    private String name; 
    private String street; 
    private String houseNo; 
    private String postalcode; 
    private String city; 
    private String country; 
    private String shortDesc; 
    private Boolean landing; // admin acceess only 
} 

バックエンド・ファサード:

@Component 
public class HotelAccessImpl extends BackendBaseAccess implements HotelAccess { 
    @Autowired 
    private AccountAccess accountAccess; 

    @Override 
    public List<Hotel> findAll() { 
     TypedQuery<Hotel> query = getEm().createQuery("FROM Hotel WHERE DELETED = false ORDER BY CREATED DESC", 
       Hotel.class); 
     List<Hotel> results = query.getResultList(); 
     return results; 
    } 

@Override 
@Transactional(value = "transactionManager", propagation = Propagation.REQUIRES_NEW) 
public Hotel upsert(Hotel hotel) { 
    if (find(hotel.getId()) == null) { 
     getEm().persist(hotel); 
    } else { 
     hotel = getEm().merge(hotel); 
    } 
    getEm().flush(); 
    return hotel; 
} 

} 

API(iはメソッドレベルで "専用" アクセスを制限コントローラ)

conrete例えば以下

[OK]を、

@RestController 
@RequestMapping("hotel") 
public class HotelController extends BaseController { 
private static Logger logger = LogManager.getLogger(HotelController.class); 

@Autowired 
private FileAccess fileAccess; 
@Autowired 
private HotelAccess hotelAccess; 
@Autowired 
private MailAccess mailAccess; 


@RequestMapping(value = "list", method = RequestMethod.GET) 
public ResponseEntity<List<Hotel>> findAll() { 
    logger.info("FindAll"); 
    return new ResponseEntity<List<Hotel>>(hotelAccess.findAll(), HttpStatus.OK); 
} 

@RequestMapping(value = "upsert", method = RequestMethod.POST) 
public ResponseEntity<Hotel> upsert(@RequestBody Hotel hotel) { 
    logger.info("Upsert: " + hotel.getName()); 
    if (isAuthorized(hotel.getAccount())) { 
     Hotel response = hotelAccess.upsert(hotel); 
     if (response.isInitial()) { 
      mailAccess.sendHotelUpsert(response); 
     } 
     return new ResponseEntity<Hotel>(response, HttpStatus.OK); 
    } else { 
     return new ResponseEntity<>(HttpStatus.FORBIDDEN); 
    } 
} 
@Secured({ "ROLE_ADMIN" }) 
@RequestMapping(value = "delete", method = RequestMethod.POST) 
public ResponseEntity<Hotel> delete(@RequestBody Hotel hotel) { 
    logger.info("Delete: " + hotel.getId()); 
    boolean deleted = hotelAccess.delete(hotel); 
    return (deleted) ? new ResponseEntity<>(HttpStatus.OK) : new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); 
} 
+0

これをより具体的な問題にスケールする必要があります。 See [ask] – charlietfl

+0

にいくつかのコードを追加しました。 –

答えて

0

エンティティデータのマーシャリングとアンマーシャリングを確実にすることを検討する必要があります。言い換えれば

、管理者以外のユーザーのために、あなただけのマーシャルフィールドクライアントとアンマーシャリングフィールド Aとクライアント Bから ABにしたいと思います。管理者ユーザーの場合は、すべてのフィールドをマーシャリングおよびアンマーシャリングする必要があります。

ユーザーコンテキストが管理者でない場合、フィールドCについては、Javascriptベースのクライアントに安全な情報が漏洩するのを防ぐ必要があります。管理者以外のユーザーのためにフィールドCの挿入/更新を防止することは、フィールドCの値の保護された性質によっては十分ではありません。

+0

実行時にロールベースのマーシャリングを行う方法はありますか?今のところ、マーシャリングはコントローラメソッドが保持するエンティティに基づいてジャクソンによって行われます。私の場合は、エンティティのすべてのメンバ(管理メンバを含む)です。 –

+0

...メンバcが(セキュリティルールのために)エンティティにアンマーシャリングされず、エンティティがデータベースに書き込まれるとどうなりますか?列の更新をスキップして休止するか、列をNULL値で上書きしますか? –

0

あまりにも難しいことではありません。同じまたは異なるコントローラで

  1. 、のために別々のAPIを作成するには、/は、通常のユーザと管理者ユーザーのための他のセットに1セットの読み書きを行います。

  2. 春のセキュリティを使用すると、管理者のみが管理APIにアクセスできるようになります。通常のユーザは読み込み処理APIについては

  3. 、あなたは通常、ユーザが値を送信する前に見られたくないものは何でもZの要素うちナル:書き込みの

    @RequestMapping(value = "/my/foo/{id}", method = RequestMethod.GET) 
        public Foo getFoo(@PathVariable String id, HttpServletResponse response) { 
         Foo foo = fooDao.getFoo(id); 
         if (foo != null) { 
          foo.setC(null); 
          return foo; 
         } else { 
          response.setStatus(HttpServletResponse.SC_NOT_FOUND); 
          return null; 
         } 
        } 
    
  4. 、取得要素を内部オブジェクトの内部IDに基づいてHibernateから取得し、更新可能な受信オブジェクトのフィールドのみで更新し、そのオブジェクトをデータベースに保持します。

+0

この方法は私には重複しているようです。私もこれを行うと考えられましたが、これが良い練習であるかどうかはわかりません.Narosのアドバイスはこれを行うためのよりよい方法です。 –

+0

冗長性を証明する2つの実装の部分は、必要に応じて共通のプライベート(非外部的に利用可能な)メソッドに分解することができます。しかし、API URLに基​​づいてセキュリティを確保するほうが安全です(39〜40行目(https://github.com/gmazza/tightblog/blob/b32c215e5c904070d02d6a837496819e05b953f4/app/src/main/webapp/WEB -INF/security.xml#L39))ので、ロールが満たされない限りメソッドを入力することはできません。すべてのユーザーが入力できる共通のメソッドを作成し、メソッドの実装に依存して通常のユーザーが実行しないようにします管理者だけが許可されているもの –