2

Currently our web projects need to anonymize some data.
(for example a security number like 432-55-1111 might appear as 432-55-**) These datas may contain email, id, price, date ,and so on.

The tables' name and columns that needed to be masked was saved in DB.
We are using spring security to judge a user whether he can see the data or not.
The data domain object(CMP) may be get from SQL or JPQL(named query or native query)or JPA Load method or Mainframe.

We need to find a best efficient way (not the DB end) to mask these data dynamically.
If we use a interceptor at the EJB method end , we need to annotation all the Object(DTO) and all the columns. That's may be low efficiency.
Any body know how can we invoke a method(like a interceptor) when finish SQL executed and named query(native query) exectued, and we can call a method to mask the result by the query and user id.

Or other ways.

It would be good to have this in the lowest level, so that other applications like reporting would not need a separate solution.

Our project's architecture is JSF+Spring+EJB 3.0+JPA 1.0.
We have many web projects.
For JPA some projects using EclipseLink 2.2 ,some using Hibernate.

UPDATE: More information about our projects. We have many web project about different feature.So we have many ejb projects associated with them. Every ejb has DAO to get their CMP by call JPQL or get(class, primarykey) metod.Like below:

Query   query = em.createNamedQuery(XXXCMP.FIND_XXX_BY_NAME);
                query.setHint(QueryHints.READ_ONLY, HintValues.TRUE);
                query.setParameter("shortName", "XXX").getSingleResult();

Or

XXXCMP screen = entityManager.find(XXXCMP.class, id);

The new EJB services code converter to transfrom the data from CMP to DTO.
The converter as below:

/**
 * Convert to CMP.
 * 
 */
CMP convertToCMP(DTO dto, EntityManager em);

/**
 * Convert CMP to domain object with all fields populated, the default scenario is
 * <code>EConvertScenario.Detail</code>.
 * 
 */
DTO convertFromCMP(CMP cmp, EntityManager em);

But some old services use their own methods to convert CMP.Also some domain services used for search lazy paing, they also don't use the converter.

We want to mask the data before the CMP convert to DTO.

Hadi
  • 36,233
  • 13
  • 65
  • 124
FishGel
  • 1,100
  • 2
  • 16
  • 27

2 Answers2

0

You can try EntityListener to intercept entity loading into the persistence context with @PostLoad annotation.

Else, can try within accesor methods(getter/setter) which I think is suitable for masking/formatting etc.

Edit : (based on comments & question update)

You can share entity/DTO across appications

public String getSomethingMasked(){

   return mask(originalString);
}
  • The data retrieval pattern isn't uniform across applications. If all the applications are using same database, it must be generalized. There is no point of writing same thing again with different tools. Each application might apply business logic afterwards.

    Probably, you can have a separate project meant for interacting with database & then including it in other applications for further use. So it will be a common point to change anything, debug, enhance etc.

  • You are using Eclipselink, Hibernate & other custom ways for fetching data & you require minimal workaround, which from my perspective seems difficult.

    Either centralize the data retrieval or make changes all over separately if possible, which I think is not feasible, compromising consistency.

Nayan Wadekar
  • 11,444
  • 4
  • 50
  • 73
0

In this case, you may intercept the JSF's conversion fase. This solution applies to JSF views, not to reportings.

@FacesConverter("AnonymizeDataConverter")
public class AnonymizeDataConverter implements Converter{

    @Override
    public Object getAsObject(FacesContext context, UIComponent component,
        String value) {

        return getAnonymisedData(value);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component,
            Object value) {

        return getAnonymisedData(value);     
    }

    public static String getAnonymisedData(Object data) {
        if (data == null) 
            return "";

        String value = data.toString().trim();

        if (!value.isEmpty())
            return value.substring(0, value.lenght() - 4) + "**";

        return "";
    }

}
Rafael Perez
  • 162
  • 4
  • 14