How to handle column Hashing with JPA - jpa

i have a User entity with a password property. I want to store bcrypt hashed passwords in the database.
How can i handle the hashing as transparent as possible with jpa/eclipselink.
I want the hashing to take plase as late as possible and for the code that accesses the user to know as few as possible about the underlying hash mechanism (or its existence).
Currently i only access the password in jpql queries and the user doesn't even have a getPassword() method.
Greetings,
Laures

You can have different access methods; one set for the user and another for the JPA provider that handle the data underneath as required. The access methods required by the provider must deal with the data as it is needed to persist in the database. When using property access, just mark the get/set methods you want the provider to use with the mapping annotations, and either use different naming for user methods or mark them as transient. You are then free to store the data in the User entity how ever is needed.

Related

JHipster Role based masking of certain columns

In a JHipster based project, we need to selectively filter out certain columns based on role/user logged in. All users will be able to view/modify most of the columns, but only some privileged users will be able to view/modify certain secure fields/columns.
It looks like the only option to get this done is using EntityListeners. I can use an EntityListener and mask a certain column during PostLoad event. Say for example, I mask the column my_secure_column with XXX and display to the user.
User then changes some other fields/columns (that he has access to) and submits the form. Do I have to again trap the partially filled in entity in PreUpdate event, get the original value for my_secure_column from database and set it before persisting?
All this seems inefficient. Scoured several hours but couldn't find a specific implementation that best suits this use case.
Edit 1: This looks like a first step to achieving this in a slightly better way. Updating Entities with Update Query in Spring Data JPA
I could use specific partial updates like updateAsUserRole, updateAsManagerRole, etc., instead of persisting the whole entity all the time.
#Repository
public interface CompanyRepository extends JpaRepository<Company, Integer> {
#Modifying(clearAutomatically = true)
#Query("UPDATE Company c SET c.address = :address WHERE c.id = :companyId")
int updateAddress(#Param("companyId") int companyId, #Param("address") String address);
}
Column based security is not an easy problem to solve, and especially in combination with JPA.
Ideally you like to avoid even loading the columns, but since you are selecting entities this is not possible by default, so you have to remove the restricted content by overriding the value after load.
As an alternative you can create a view bean (POJO) and then use JPQL Constructor Expression. Personally I would use CriteriaBuilder. construct() instead of concatenating a JPQL query, but same principle.
With regards to updating the data, the UI should of cause not allow the editing of restricted fields. However you still have to validate on the backend, and I would recommend that you check if the column was modify before calling JPA. Typically you have the modifications in a DTO and would need to load the Entity anyway, if a restricted column was modified, you would send an error back. This way you only call JPA after the security has been checked.

Design: What is the best approach to updating part of a database record?

This question concerns the best design approach rather than a particular technical technique. I have a database table that contains system user's details i.e: username, password, firstname, lastname (these attributes can only be changed by an administrator). The rest of the user record contains address, phone number, mobile number, etc (these attributes can only be changed by the user).
I therefore need 2 forms, an 'admin' form and a 'user' form, with a different set of editable fields on each, and appropriate role-based security to control usage.
Here are two approaches I could take:
Approach 1. Each form has it's own backing bean representing just the editable fields on the form. On 'Save', the backing bean calls a specific DAO method (e.g. UpdateUser_Admin or UpdateUser_User) to perform a partial update of the user record. This approach therefore involves 2 forms, a backing bean for each form, and 2 methods in the DAO class.
Approach 2. There are 2 forms as before, but each form re-creates the entire User object through the use of input fields for the editable fields and hidden fields for the non-editable fields. Both forms would use the same backing bean representing ALL of the User attributes. There would only need to be one method in the DAO - to update ALL fields in the User record.
The second approach seems to make sense to me, but I'm new to development and I'd be grateful if readers could advise if I'm missing something. I've already considered splitting the User table into 2 separate tables but that is not practical in this case. Thank you for your advice.
As a rule: don't create DAO methods updating only a single field / attribute.
Don't split User entity into 2 tables.
DAO are created to manage entities, thus use one DAO for each class and code only a single update method for each DAO.
If you are not sure of having the complete entity follow this steps in the service layer
get data from form (at least id and field you want to update)
retrieve Object representing entity from database (with DAO::readById(id) for example)
update the field you need in the java Object
call DAO::update
NOTE: I ommited populating DTO to DBO objects

JPA: How to exclude certain fields from loading from database table

i have a class User which holds an email address and password for authentication users in my web application. This user is mapped to the database via JPA / Eclipselink.
My question is, how can i prevent JPA from loading the password field back from the database? Since i will access the user object in my web app, i'm uncomfortable regarding security with sending the password to the browser.
Is there any way i can prevent loading the field in JPA / EclipseLink? Declaring the field transient is not an option, since i want to store it on the database when i call persist() on the user object.
Thanks,
fredddmadison
JB Nizet has a valid point. Retrieving it and serializing it in the Http response are two separate concerns.
I'm not sure what you're using to serialize your data. If it this is a REST API, consider Jackson's #JsonIgnore annotation or Eclipselink MOXy's #XmlTransient equivalent. If this uses Java EL (facelets, jsps), you should be able to select only the bean properties of interest.
If you really must do this during retrieval, consider JPQL's/Criteria API's constructor functionality. Ensure that the object has a constructor that accepts the specified parameters, and keep in mind that it won't be managed in the persistence context if it's retrieved in this manner.
SELECT NEW my.package.User(u.id, u.name, u.etc) FROM User u
Alternatively, consider the #PostLoad lifecycle callback.
#PostLoad
private void postLoad() {
this.password = null;
}
Finally, this might not be the case, but I would like to reinforce the notion that passwords shouldn't be stored in plaintext. I mention this because returning a hashed salted password that used a secure algorithm (bCrypt, multiple iteration SHA-512, etc) wouldn't be that big a deal (but still isn't ideal).
I have the similar problem. But in my case I have many #OneToMany relationships inside of Entity class and some of them are EAGER. When I query against this Entity it loads all of them, although for web service I need only some of them.
I tried TupleQuery. But it's not the solution because to get needed OneToMany relationships I have to join and get many duplicate rows of the main query. It makes the result more heawy, than economic.

how do I prevent spring mvc overwriting sessionattributes from request

I have an MVC spring application where the user logs on, this stores a User #SessionAttribute , which I refer to subsequently e.g. when updating a Customer object in a POST request I want the session User info to add to this object.
My problem is when I access the #ModelAttribute("user") User object in the customer POST, spring has bound request parameters into it i.e. the User.name has the value of the Customer.name from the submitted form.
NB I've kind of hacked this in that all controllers are subclasses of my AppController, which is where the #SessionAttributes are declared. But the principle would be the same if it was a single controller.
So can I prevent spring binding form:customer name value to User.name?
(I suspect webflow would be a more suitable framework for this, but don't have the time available right now to rewrite using this)
You can allow or disallow binding of certain fields of your model attributes using #InitBinder:
#InitBinder("user")
public void configureBindingOfUser(WebDataBinder binder) {
binder.setAllowedFields(); // No fields allowed
}
However, I don't think it's a good idea to use #SessionAttributes to store the current user or other similar objects. #SessionAttributes was originally designed to maintain state of form-backing objects between GET and POST requests, not as a general purpose way to access a session.
Perhaps it would be better to use session-scoped beans or custom argument resolvers to access this kind of information.

Entity Framework: Inheritance, change object type

Let's say, I have 2 classes in the model: User (mapped to USERS table) and PrivilegedUser (inherits User, additional info is stored in PRIVILEGEDUSERS table).
Now, I have a row in USERS (and instance of User) and need to convert that user to PrivilegedUser (i.e. to create a record in PRIVILEGEDUSERS with the same Id). Is there a way to do this without Delete/Insert?
The problem is you don't have PRIVILEGEDUSERS representation in the model, so you cannot create only that part of PrivilegedUser.
It was just an example. PrivilegedUser may have some discount or personal manager or whatever in addition to ordinary User properties. In the same time, there are other tables which need to reference users regardless of concrete User type. I've implemented it using Table-per-Type inheritance mode. In the database level it's very simple to convert users from one type to another (you just need to insert or delete record from extension table). But in EF you have only UserSet which stores both User and PrivilegedUser objects. That's why I ask is it possible to replace existing User object with PrivilegedUser keeping existing Id and without deleting record from USERS table.
No you cannot.
As explained by this article, EF (3.5) does not support this feature. You must use stored procedure to accomplish this.
You need to change your world view. Your view is that you have standard users with standard privileges and super users with additional privileges. The privileges aren't enumerated, they are implicit.
The new world view is that you maintain a list of all privileges, both standard and super and then in a mapping table you create a many to many map of which users have which privileges. When a user is granted super privileges, you just add mappings for the appropriate privileges to the mapping table. You don't need a PrivilegedUser class, just a list of privileges in the User class. The privileges may be either standard or super.
It seems wrong that you have two tables representing users.
Would it not be better to have a Users table (for all users) and then a UserPrivileges table, representing what they are allowed to do? This way, no deletes/Inserts are needed, and you can reference just one table for users.
A third table can be used to represent the actual privileges.
Users
Id Username ...
UserPrivileges
UserId PrivilegeId
Privileges
Id Description
Regarding inheritance in EF take a look at this site, which explains the three different ways to use inheritance in EF.
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/01/20/entity-framework-inheritance-types.aspx
As said, you cannot. Either by stored procedures or by custom insert/update query. I had similar problem, now I'm using solution that i described in this answer: https://stackoverflow.com/a/28380804/2424989