Problems with AccessReferenceMap

841 Views Asked by At

I am using AccessReferenceMap from OWASP to secure my ids in URLs. The problem is that when list of IDs to be obfuscated is related to particular customer. Here is my configuration:

<bean id="hyperlinkMapping" class="web.security.HyperlinkMapping" scope="session">
    <aop:scoped-proxy />
</bean>

<bean id="tracksAccessMap" class="web.security.EntityAccessMap"
        scope="session" factory-method="create">
    <constructor-arg index="0" ref="allTrackIdsForCustomer" />
    <aop:scoped-proxy/>
</bean>

<bean id="allTrackIdsForCustomer" scope="session"
    factory-bean="webTrackDAO"
    factory-method="findAllTrackIdsForCustomer">
    <aop:scoped-proxy/>
</bean>

<bean id="webTrackDAO" class="web.repository.impl.WebTrackDAOImpl"/>

EntityAccessMap:

package web.security;

import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.owasp.esapi.AccessReferenceMap;
import org.owasp.esapi.errors.AccessControlException;
import org.owasp.esapi.reference.RandomAccessReferenceMap;
import org.springframework.stereotype.Component;

import core.domain.Entity;

@Component
public class EntityAccessMap<T extends Entity> implements AccessMap<T> {
    private static Logger logger = Logger.getLogger(EntityAccessMap.class);

    private static final long serialVersionUID = -436098952674898327L;
    private AccessReferenceMap<String> map = new RandomAccessReferenceMap();

    public EntityAccessMap() {
    }

    private EntityAccessMap(final List<T> entities) {
        logger.info("Entities size: " + entities.size());
        for (final T entity : entities) {
            map.addDirectReference(entity);
        }
    }

    public <T extends Entity> AccessMap<T> create(final List<T> entities) {
        logger.info("calling create with entities' size " + entities.size() );
        return new EntityAccessMap<>(entities);
    }

    public String getIndirectReference(final T entity) {
        for( Iterator it = map.iterator(); it.hasNext(); ) {
            logger.info((String)it.next().toString());
        }
        logger.info("Entity: " + map.getIndirectReference(entity));
        return map.getIndirectReference(entity);
    }

    public T getDirectReference(final String indirectReference) {
        try {
            return map.getDirectReference(indirectReference);
        } catch (AccessControlException e) {
            throw new IllegalArgumentException("Indirect Reference is not valid", e);
        }
    }
}

AccessMap:

package web.security;

import java.io.Serializable;

import core.domain.Entity;

public interface AccessMap<T extends Entity> extends Serializable {
    String getIndirectReference(final T entity);
    T getDirectReference(final String indirectReference);
}

HyperlinkMapping:

package web.security;

import java.io.Serializable;

import org.springframework.beans.factory.annotation.Autowired;

import core.domain.track.Track;

public class HyperlinkMapping implements Serializable {
    private static final long serialVersionUID = -2011016815710653498L;

    @Autowired AccessMap<Track> tracksAccessMap;

    public String getTrackId(final Track track) {
        return tracksAccessMap.getIndirectReference(track);
    }

    public Track getTrack(final String indirectId) {
        return tracksAccessMap.getDirectReference(indirectId);
    }
}

So, what I want to achieve: tracksAccessMap should be filled only with customer's related ids, not whole set. How to initialize all these beans after customer's login (and setting customerId session attribute)?

EDIT 1: additional code:

TracksController:

package web.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import core.constants.WebConstants;
import web.service.TrackService;

@Controller
@Secured("ROLE_USER")
@RequestMapping(WebConstants.WEB_MY)
@Scope("session")
public class TracksController {

    @Autowired
    private TrackService trackService;
    @Autowired
    private HyperlinkMapping hyperlinkMapping;

    @RequestMapping(value=WebConstants.WEB_MYTRACKS, method = RequestMethod.GET, produces = "application/json")
    public ModelAndView showTracks( HttpServletRequest  request, @RequestParam(value = "pageSize", required = false) Integer pageSize ) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("pagedListHolder",trackService.getTracksList(request, pageSize == null ? 10 : pageSize ));
        mv.addObject("hyperlinkMapping",hyperlinkMapping);
        return mv;
    }
}

centerColTracks.jsp

<c:forEach items="${pagedListHolder.pageList}" var="item">
    <tr>
        <td>${item.id}</td>
        <td style="color:blue;text-align:right"><a href="<c:url value="${request.getRequestURL()}/my/tracks/${hyperlinkMapping.getTrackId(item)}"/>">${item.name}</a></td>
        <td style="color:blue;text-align:right">${item.trackDate}</td>
        <td style="color:blue;text-align:right">${item.description}</td>
    </tr>
</c:forEach>

hyperlinkMapping.getTrackId(item) should return ONLY trackId (taken from AccessReferenceMap) related ONLY for customer logged in. In other words - hyperlinkMapping should be instantiated right after the login.

I have two ideas how to do this: 1. AOP with after-returning advice, or 2. use SimpleUrlAuthenticationSuccessHandler, where I can instantiate HyperlinkMapping after login. Or I can use it with the current implementation and I just simply forgot something?

0

There are 0 best solutions below