Package org.fcrepo.security.http

Source Code of org.fcrepo.security.http.AuthZHttpRequestAttributesFilter

package org.fcrepo.security.http;

import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.fcrepo.server.security.jaas.auth.AuthHttpServletRequestWrapper;
import org.fcrepo.server.security.jaas.auth.UserPrincipal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author ajs6f
* @author cs2@st-andrews.ac.uk
*/
public class AuthZHttpRequestAttributesFilter implements Filter {

  // names of HTTP headers to aggregate HTTP attribute
  private Set<String> names;

  // name of the Shibboleth header that contains the principal's name
  private String principalHeader;

  // attribute in which to store authN data
  static final String FEDORA_ATTRIBUTES_KEY = "FEDORA_AUX_SUBJECT_ATTRIBUTES";

  private static final Logger logger = LoggerFactory
      .getLogger(AuthZHttpRequestAttributesFilter.class);

  /**
   * setNames set the list of attribute names to look for
   *
   * @param names
   *            contains space separated attribute names
   */
  public void setNames(String names) {
    this.names = new HashSet<String>(Arrays.asList(names.split(" ")));
  }

  /**
   * setPrincipalHeader set the name of the Shibboleth header whgich contains
   * the principal's name
   *
   * @param principalHeader
   *            contains name of header containing principal's name
   */
  public void setPrincipalHeader(String principalHeader) {
    this.principalHeader = principalHeader;
  }

  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;

    // this is the map we will actually store into the request attribute
    Map<String, String[]> subjectAttributes = new HashMap<String, String[]>();

    // we use two loops to populate attributes in case we have multiple
    // homonymic headers in addition to multivalued headers
    for (String name : names) {
      logger.debug("Looking for header with name: {}", name);
      Set<String> headervalues = new HashSet<String>();
      for (Enumeration<String> retrievedheadervalues = req
          .getHeaders(name); retrievedheadervalues.hasMoreElements();) {
        logger.debug("Retrieved header with name: {}", name);
        String value = retrievedheadervalues.nextElement();
        logger.debug("Now adding value: " + value + " to field " + name);

        headervalues.add(value);
      }
      // convert headervalues to a String[] and store it
      subjectAttributes.put(name, headervalues.toArray(new String[0]));
    }

    String[] principalNames = subjectAttributes.get(principalHeader);

    if (isValid(principalNames)) {

      logger.debug("Trying to set principal to new Principal with name="
          + principalNames[0]);

      // get name of principal and inject it into request
      // we use here a FeSL implementation of java.security.Principal
      UserPrincipal principal = new UserPrincipal(principalNames[0]);
      AuthHttpServletRequestWrapper authRequest = new AuthHttpServletRequestWrapper(
          req);
      authRequest.setUserPrincipal(principal);

      logger.debug("Principal has been set to " + principal);

      // can inject other attributes
      authRequest.setAttribute(FEDORA_ATTRIBUTES_KEY, subjectAttributes);
      if (logger.isDebugEnabled()) {
        logger.debug("Added " + subjectAttributes + " to "
            + FEDORA_ATTRIBUTES_KEY);
      }
      if (chain != null)
        chain.doFilter(authRequest, response);

    } else {
      // not authenticated, so just pass original request through
      // to rest of chain
      if (chain != null)
        chain.doFilter(request, response);
    }
  }

  /**
   * @param principalnames
   *            array of Strings containing possible names for the security
   *            Principal
   * @return whether or not the array contains exactly one name of more than 0
   *         length
   */
  private Boolean isValid(String[] principalnames) {
    logger.debug("Checking potential principal name.");
    // no principal name found
    if (principalnames == null) {
      logger.debug("Principal name was null!");
      return false;
    }
    // no principal name found, but there was some empty header
    if (0 == principalnames.length) {
      logger.debug("Principal name was an array of zero length!");
      return false;
    }

    // more than one principal name found
    if (principalnames.length > 1) {
      logger.error(new Exception(
          "More than one principal for authentication found in HTTP request!")
          .toString());
      return false;
    }

    // make sure that first principal name is not empty
    if (principalnames[0] == null || principalnames[0].length() == 0) {
      return false;
    }
    // we have a valid Principal name!
    logger.debug("Principal name {} was valid!", principalnames[0]);
    return true;
  }

  /**
   * init initialise filter
   *
   * @param config
   *            not used
   */
  @Override
  public void init(FilterConfig config) throws ServletException {
    this.init();
  }

  public void init() throws ServletException // {{{
  {
    // add principal header to list of names to look for
    names.add(principalHeader);

    // log initialisation
    logger.info("Initializing {}", this.getClass().getName());
  }

  @Override
  public void destroy() {
    logger.info("Destroying {}", this.getClass().getName());
  }

  public String getNames() {
    // we use a loop-and-test to ensure that the results of getNames() could be used for setNames()
    StringBuffer result = new StringBuffer();
    Iterator<String> iter = names.iterator();
    while (iter.hasNext()) {
      result.append(iter.next());
      if (iter.hasNext()) {
        result.append("");
      }
    }
    return result.toString();
  }

  public String getPrincipalHeader() {
    return principalHeader;
  }

}
TOP

Related Classes of org.fcrepo.security.http.AuthZHttpRequestAttributesFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.