Package com.dotcms.rest

Source Code of com.dotcms.rest.WebResource

package com.dotcms.rest;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import com.dotcms.repackage.javax.ws.rs.core.Response;

import com.dotcms.rest.exception.SecurityException;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.business.web.WebAPILocator;
import com.dotmarketing.cms.login.factories.LoginFactory;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.util.Config;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.SecurityLogger;
import com.dotmarketing.util.UtilMethods;
import com.liferay.portal.model.Company;
import com.liferay.portal.model.User;
import com.dotcms.repackage.com.sun.jersey.core.util.Base64;
import com.dotcms.repackage.com.sun.jersey.spi.container.ContainerRequest;

public class WebResource {

  /**
   * <p>Checks if SSL is required. If it is required and no secure request is provided, throws a ForbiddenException.
   *
   * @param request
   */

  protected void init(HttpServletRequest request) {
    checkForceSSL(request);
  }

  /**
   * <p>1) Checks if SSL is required. If it is required and no secure request is provided, throws a ForbiddenException.
   * <p>2) If 1) does not throw an exception, returns an {@link InitDataObject} with a <code>Map</code> containing
   * the keys and values extracted from <code>params</code>
   *
   *
   * @param params a string containing parameters in the /key/value form
   * @param request
   * @return an initDataObject with the resulting <code>Map</code>
   */

  protected InitDataObject init(String params, HttpServletRequest request) {

    checkForceSSL(request);

    InitDataObject initData = new InitDataObject();

    if(!UtilMethods.isSet(params))
      return initData;

    initData.setParamsMap(buildParamsMap(params));
    return initData;
  }

  /**
   *
   * <p>1) Checks if SSL is required. If it is required and no secure request is provided, throws a ForbiddenException.
   * <p>2) If 1) does not throw an exception, returns an {@link InitDataObject} with:
   *
   * <br>a) a <code>Map</code> with the keys and values extracted from <code>params</code>.
   *
   *<br><br>if <code>authenticate</code> is set to <code>true</code>:
   * <br>b) , an authenticated {@link User}, if found.
   * If no User can be retrieved, and <code>rejectWhenNoUser</code> is <code>true</code>, it will throw an exception,
   * otherwise returns <code>null</code>.
   *
   * <br><br>There are five ways to get the User. They are executed in the specified order. When found, the remaining ways won't be executed.
   * <br>1) Using username and password contained in <code>params</code>.
   * <br>2) Using username and password in Base64 contained in the <code>request</code> HEADER parameter DOTAUTH.
   * <br>3) Using username and password in Base64 contained in the <code>request</code> HEADER parameter AUTHORIZATION (BASIC Auth).
   * <br>4) From the session. It first tries to get the Backend logged in user. If no user found, tries to get the Frontend logged in user.
   *
   *
   * @param params a string containing the URL parameters in the /key/value form
   * @param authenticate
   * @param request
   * @param rejectWhenNoUser determines whether a SecurityException is thrown or not when authentication fails.
   * @return an initDataObject with the resulting <code>Map</code>
   */

  protected InitDataObject init(String params, boolean authenticate, HttpServletRequest request, boolean rejectWhenNoUser) throws SecurityException {

    return init(params, authenticate, request, rejectWhenNoUser, null);
  }

  /**
   *
   * <p>1) Checks if SSL is required. If it is required and no secure request is provided, throws a ForbiddenException.
   * <p>2) If 1) does not throw an exception, returns an {@link InitDataObject} with:
   *
   * <br>a) a <code>Map</code> with the keys and values extracted from <code>params</code>.
   *
   *<br><br>if <code>authenticate</code> is set to <code>true</code>:
   * <br>b) , an authenticated {@link User}, if found.
   * If no User can be retrieved, and <code>rejectWhenNoUser</code> is <code>true</code>, it will throw an exception,
   * otherwise returns <code>null</code>.
   *
   * <br><br>There are five ways to get the User. They are executed in the specified order. When found, the remaining ways won't be executed.
   * <br>1) Using username and password contained in <code>params</code>.
   * <br>2) Using username and password in Base64 contained in the <code>request</code> HEADER parameter DOTAUTH.
   * <br>3) Using username and password in Base64 contained in the <code>request</code> HEADER parameter AUTHORIZATION (BASIC Auth).
   * <br>4) From the session. It first tries to get the Backend logged in user. If no user found, tries to get the Frontend logged in user.
   *
   *
   * @param params a string containing the URL parameters in the /key/value form
   * @param authenticate
   * @param request
   * @param rejectWhenNoUser determines whether a SecurityException is thrown or not when authentication fails.
   * @param requiredPortlet portlet name which the user needs to have access to
   * @return an initDataObject with the resulting <code>Map</code>
   */

  protected InitDataObject init(String params, boolean authenticate, HttpServletRequest request, boolean rejectWhenNoUser, String requiredPortlet) throws SecurityException {

    checkForceSSL(request);

    InitDataObject initData = new InitDataObject();

    if(!UtilMethods.isSet(params))
      params = "";

    Map<String, String> paramsMap = buildParamsMap(params);
    User user = null;

    user = authenticateUser(paramsMap, request, rejectWhenNoUser);

    if(UtilMethods.isSet(requiredPortlet)) {

      try {
        if(!APILocator.getLayoutAPI().doesUserHaveAccessToPortlet(requiredPortlet, user)){
          throw new SecurityException("User does not have access to required Portlet", Response.Status.UNAUTHORIZED);
        }
      } catch (DotDataException e) {
        throw new SecurityException("User does not have access to required Portlet", Response.Status.UNAUTHORIZED);
      }

    }

    initData.setParamsMap(paramsMap);
    initData.setUser(user);

    return initData;
  }

  /**
   * Returns an authenticated {@link User}. There are five ways to get the User.
   * They are executed in the specified order. When found, the remaining ways won't be executed.
   * <br><br>1) Using username and password contained in <code>params</code>.
   * <br>2) Using username and password in Base64 contained in the <code>request</code> HEADER parameter DOTAUTH.
   * <br>3) Using username and password in Base64 contained in the <code>request</code> HEADER parameter AUTHORIZATION (BASIC Auth).
   * <br>4) From the session. It first tries to get the Backend logged in user. If no user found, tries to get the Frontend logged in user.
   *
   * @param paramsMap a map containing the URL parameters
   * @param request
   * @param rejectWhenNoUser determines whether a SecurityException is thrown or not when authentication fails.
   * @return
   */

  private User authenticateUser(Map<String, String> paramsMap, HttpServletRequest request, boolean rejectWhenNoUser) throws SecurityException  {

    boolean forcefrontendauth = Config.getBooleanProperty("REST_API_FORCE_FRONT_END_SESSION_AUTH", false);

    User user = (user = authenticateUserFromURL(paramsMap, request)) != null ? user
            : (user = authenticateUserFromHeaderAuth(paramsMap, request)) != null ? user
                : (user = authenticateUserFromBasicAuth(paramsMap, request)) != null ? user
                    : !forcefrontendauth ? (user = getBackUserFromRequest(request)) != null ? user
                        : (user = getFrontEndUserFromRequest(request))
                        : (user = getFrontEndUserFromRequest(request)) != null ? user : null;


    if(user==null && (Config.getBooleanProperty("REST_API_REJECT_WITH_NO_USER", false) || rejectWhenNoUser) ) {
      throw new SecurityException("Invalid User", Response.Status.UNAUTHORIZED);
    } else if(user==null) {
      try {
        user =APILocator.getUserAPI().getAnonymousUser();
      } catch (DotDataException e) {
        Logger.debug(getClass(), "Could not get Anonymous User. ");
      }
    }

    return user;
  }

  private User authenticateUserFromURL(Map<String, String> paramsMap, HttpServletRequest request) {

    String username = paramsMap.get(RESTParams.USER.getValue());
    String password = paramsMap.get(RESTParams.PASSWORD.getValue());

    return authenticateUser(username, password, request);
  }

  private User authenticateUserFromBasicAuth(Map<String, String> paramsMap, HttpServletRequest request) throws SecurityException  {

    // Extract authentication credentials
    String authentication = request.getHeader(ContainerRequest.AUTHORIZATION);

    if(UtilMethods.isSet(authentication) && authentication.startsWith("Basic ")) {
      authentication = authentication.substring("Basic ".length());
      String[] values = new String(Base64.base64Decode(authentication)).split(":");
      if (values.length < 2) {
        // "Invalid syntax for username and password"
        throw new SecurityException("Invalid syntax for username and password", Response.Status.BAD_REQUEST);
      }
      String username = values[0];
      String password = values[1];

      return authenticateUser(username, password, request);
    } else {
      return null;
    }
  }

  private User authenticateUserFromHeaderAuth(Map<String, String> paramsMap, HttpServletRequest request) throws SecurityException  {
    // Extract authentication credentials
    String authentication = request.getHeader("DOTAUTH");

    if(UtilMethods.isSet(authentication)) {
      String[] values = new String(Base64.base64Decode(authentication)).split(":");
      if (values.length < 2) {
        // "Invalid syntax for username and password"
        throw new SecurityException("Invalid syntax for username and password", Response.Status.BAD_REQUEST);
      }
      String username = values[0];
      String password = values[1];

      return authenticateUser(username, password, request);
    } else {
      return null;
    }
  }

  /**
   * Authenticates and returns a {@link User} using <code>username</code> and <code>password</code>.
   * If a wrong <code>username</code> or <code>password</code> are provided,
   * a SecurityException is thrown
   *
   * @param username
   * @param password
   * @param req
   * @return
   */


  private User authenticateUser(String username, String password, HttpServletRequest req) throws SecurityException {
    User user = null;
    String ip = req!=null?req.getRemoteAddr():"";

    if(UtilMethods.isSet(username) && UtilMethods.isSet(password)) { // providing login and password so let's try to authenticate

      try {

        if(LoginFactory.doLogin(username, password)) {
          Company comp = com.dotmarketing.cms.factories.PublicCompanyFactory.getDefaultCompany();

          if (comp.getAuthType().equals(Company.AUTH_TYPE_EA)) {
            user = APILocator.getUserAPI().loadByUserByEmail(username, APILocator.getUserAPI().getSystemUser(), false);
          } else {
            user = APILocator.getUserAPI().loadUserById(username, APILocator.getUserAPI().getSystemUser(), false);
          }
        } else { // doLogin returning false

          Logger.warn(this.getClass(), "Request IP: " + ip + ". Can't authenticate user. Username: " + username);
          SecurityLogger.logDebug(this.getClass(), "Request IP: " + ip + ". Can't authenticate user. Username: " + username);
          throw new SecurityException("Invalid credentials", Response.Status.UNAUTHORIZED);
        }

      }  catch(SecurityException e) {
        throw e;
      } catch (Exception e) {  // doLogin throwing Exception

        Logger.warn(this.getClass(), "Request IP: " + ip + ". Can't authenticate user. Username: " + username);
        SecurityLogger.logDebug(this.getClass(), "Request IP: " + ip + ". Can't authenticate user. Username: " + username);
        throw new SecurityException("Authentication credentials are required", Response.Status.UNAUTHORIZED);
      }

    } else if(UtilMethods.isSet(username) || UtilMethods.isSet(password)){ // providing login or password

      Logger.warn(this.getClass(), "Request IP: " + ip + ". Can't authenticate user.");
      SecurityLogger.logDebug(this.getClass(), "Request IP: " + ip + ". Can't authenticate user.");
      throw new SecurityException("Authentication credentials are required", Response.Status.UNAUTHORIZED);
    }

    return user;
  }


  /**
   * This method returns the Backend logged in user from request.
   *
   * @param request
   * @return
   */

  private User getBackUserFromRequest(HttpServletRequest req) {
    User user = null;

    if(UtilMethods.isSet(req)) { // let's check if we have a request and try to get the user logged in from it
      try {
        user = WebAPILocator.getUserWebAPI().getLoggedInUser(req);
      catch (Exception e) {
        Logger.warn(this.getClass(), "Can't retrieve Backend User from session");
      }
    }

    return user;
  }

  /**
   * This method returns the Frontend logged in user from request.
   *
   * @param request
   * @return
   */

  private User getFrontEndUserFromRequest(HttpServletRequest req) {
    User user = null;

    if(UtilMethods.isSet(req)) { // let's check if we have a request and try to get the user logged in from it
      try {
        user = WebAPILocator.getUserWebAPI().getLoggedInFrontendUser(req);
      catch (Exception e) {
        Logger.warn(this.getClass(), "Can't retrieve user from session");
      }
    }

    return user;
  }

  /**
   * This method returns a <code>Map</code> with the keys and values extracted from <code>params</code>
   *
   *
   * @param params a string in the form of "/key/value/.../key/value"
   * @return a <code>Map</code> with the keys and values extracted from <code>params</code>
   */

  private Map<String, String> buildParamsMap(String params) {

    if (params.startsWith("/")) {
      params = params.substring(1);
    }
    String[] pathParts = params.split("/");
    Map<String, String> pathMap = new HashMap<String, String>();
    for (int i=0; i < pathParts.length/2; i++) {
      String key = pathParts[2*i].toLowerCase();
      String value = pathParts[2*i+1];
      pathMap.put(key, value);
    }
    return pathMap;
  }


  private void checkForceSSL(HttpServletRequest request) {
    if(Config.getBooleanProperty("FORCE_SSL_ON_RESP_API", false) && UtilMethods.isSet(request) && !request.isSecure())
      throw new SecurityException("SSL Required.", Response.Status.FORBIDDEN);

  }

}
TOP

Related Classes of com.dotcms.rest.WebResource

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.