-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Forcing a non-updatable column to be updated?!?!?!
PostPosted: Wed May 19, 2010 6:07 pm 
Newbie

Joined: Sun Jul 10, 2005 10:20 am
Posts: 17
Location: London
Hi all,

I've got an entity with a column (which is also the candidate key and the field used for database equality) defined as follows:

Code:
@Column(name = "ROLE_NAME", updatable = false, nullable = false, unique = true)
/** The role name */
private final String roleName;


I defined the column as updatable = false. I was expecting that whenever I set a different value in roleName for the same PK, HB would throw an exception (pls note I haven't got a setter method for this column). I was able to "hack" the value with the following code:

Code:
@Test(groups = { "integration" })
public void testUpdateRoleNameGeneratesException() throws Exception {

   Role role = new Role(NULL_ID, ROLE_NAME);
   Long rolePk = roleDao.saveOrUpdate(role);
   Role actualRole = this
         .validateAndReturnRoleAfterInsertion(rolePk, role);
   System.err.println("actualRole: " + actualRole);

   // It now tries to update the ROLE name and this should result in an
   // exception
   Field roleName = Role.class.getDeclaredField("roleName");
   Assert.assertNotNull(roleName,
         "Couldn't find the role name field in the Role entity!");
   // Hack
   roleName.setAccessible(true);
   roleName.set(role, "hackedValue");
   // This should generate an exception, since the name is a read-only
   // field, but it doesn't
   Long updatedRolePk = roleDao.saveOrUpdate(role);
   Role hackedRole = roleDao.findByPk(Role.class, updatedRolePk);
   System.err.println("hacked role: " + hackedRole);

}


The test above generates the following output:

actualRole: Role ( id = 25 roleName = roleName version = 0 )
hacked role: Role ( id = 25 roleName = hackedValue version = 0 )

Is this normal?


Top
 Profile  
 
 Post subject: Re: Forcing a non-updatable column to be updated?!?!?!
PostPosted: Thu May 20, 2010 3:01 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Yes it is normal. Setting update=false doesn't imply that Hibernate verifies that you have not change the value. It just means that Hibernate ignores it when sending updates to the database. Thus, the in-memory state and the database state will differ. If you want your somewhat strange test case to forget about the hacked role, you'll need to clear the session (or at least evict the role from the session) before the call to roleDao.findByPk().


Top
 Profile  
 
 Post subject: Re: Forcing a non-updatable column to be updated?!?!?!
PostPosted: Thu May 20, 2010 3:08 am 
Newbie

Joined: Sun Jul 10, 2005 10:20 am
Posts: 17
Location: London
nordborg wrote:
Yes it is normal. Setting update=false doesn't imply that Hibernate verifies that you have not change the value. It just means that Hibernate ignores it when sending updates to the database. Thus, the in-memory state and the database state will differ. If you want your somewhat strange test case to forget about the hacked role, you'll need to clear the session (or at least evict the role from the session) before the call to roleDao.findByPk().


Ok, one thing I forgot to mention is that the test above is not complete, but I posted only the relevant bits. I actually deleted it now since it doesn't make sense to test that the non-updatable option can be enforced, since it can't.

Thanks for your answer. So if I understood correctly there is no mechanism in Hibernate to enforce at the memory level for a field to be read-only and a hack like the above would simply work. I think that if HB put a proxy in between the session and the real entity this kind of enforcement would be possible. What do you think?


Top
 Profile  
 
 Post subject: Re: Forcing a non-updatable column to be updated?!?!?!
PostPosted: Thu May 20, 2010 3:23 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
It might be possible but I don't think it would be worth the hassle. Hibernate must, for example, set the initial value when the entity is loaded from the database, and this should of course not be intercepted by the proxy, meaning that the proxy must have a way to know when Hibernate is doing stuff and when something else is trying to "hack" it's way around. If you need to prevent hacks like in the example, you should look into running your code in a security-controlled sandbox.


Top
 Profile  
 
 Post subject: Re: Forcing a non-updatable column to be updated?!?!?!
PostPosted: Thu May 20, 2010 3:44 am 
Newbie

Joined: Sun Jul 10, 2005 10:20 am
Posts: 17
Location: London
nordborg wrote:
It might be possible but I don't think it would be worth the hassle. Hibernate must, for example, set the initial value when the entity is loaded from the database, and this should of course not be intercepted by the proxy, meaning that the proxy must have a way to know when Hibernate is doing stuff and when something else is trying to "hack" it's way around. If you need to prevent hacks like in the example, you should look into running your code in a security-controlled sandbox.


I don't know. Hibernate already has a mechanism to detect changes in value to properties (e.g. dynamic-update=true). In my view it would be a simple matter of checking whether metadata have been specified with updatable=false, check the value of the property sent for update, and if it differs from the value loaded from the db, throw a HibernateException like "Tried to update a non-updatable field: [field-name]". This is BTW the same mechanism used for versioning, isn't it?


Top
 Profile  
 
 Post subject: Re: Forcing a non-updatable column to be updated?!?!?!
PostPosted: Thu May 20, 2010 4:04 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
I don't see what is related to versioning...

I guess it would be possible to do what you describe, but it has nothing to do with a proxy sitting in-between and stopping changes. At the time the modification is detected (during commit or flush) the in-memory state has already changed.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.