Package com.orientechnologies.orient.server.network.protocol.http.command

Source Code of com.orientechnologies.orient.server.network.protocol.http.command.OServerCommandAuthenticatedDbAbstract

/*
    *
    *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
    *  *
    *  *  Licensed under the Apache License, Version 2.0 (the "License");
    *  *  you may not use this file except in compliance with the License.
    *  *  You may obtain a copy of the License at
    *  *
    *  *       http://www.apache.org/licenses/LICENSE-2.0
    *  *
    *  *  Unless required by applicable law or agreed to in writing, software
    *  *  distributed under the License is distributed on an "AS IS" BASIS,
    *  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    *  *  See the License for the specific language governing permissions and
    *  *  limitations under the License.
    *  *
    *  * For more information: http://www.orientechnologies.com
    *
    */
package com.orientechnologies.orient.server.network.protocol.http.command;

import java.io.IOException;
import java.util.List;

import com.orientechnologies.common.concur.lock.OLockException;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
import com.orientechnologies.orient.core.db.record.ODatabaseRecordInternal;
import com.orientechnologies.orient.core.exception.ODatabaseException;
import com.orientechnologies.orient.core.exception.OSecurityAccessException;
import com.orientechnologies.orient.core.id.ORecordId;
import com.orientechnologies.orient.core.metadata.security.OUser;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.serialization.serializer.OStringSerializerHelper;
import com.orientechnologies.orient.server.network.protocol.http.OHttpRequest;
import com.orientechnologies.orient.server.network.protocol.http.OHttpRequestException;
import com.orientechnologies.orient.server.network.protocol.http.OHttpResponse;
import com.orientechnologies.orient.server.network.protocol.http.OHttpSession;
import com.orientechnologies.orient.server.network.protocol.http.OHttpSessionManager;
import com.orientechnologies.orient.server.network.protocol.http.OHttpUtils;

/**
  * Database based authenticated command. Authenticats against the database taken as second parameter of the URL. The URL must be in
  * this format:
  *
  * <pre>
  * <command>/<database>[/...]
  * </pre>
  *
  * @author Luca Garulli
  *
  */
public abstract class OServerCommandAuthenticatedDbAbstract extends OServerCommandAbstract {

   public static final char   DBNAME_DIR_SEPARATOR   = '$';
   public static final String SESSIONID_UNAUTHORIZED = "-";
   public static final String SESSIONID_LOGOUT       = "!";

   @Override
   public boolean beforeExecute(final OHttpRequest iRequest, OHttpResponse iResponse) throws IOException {
     super.beforeExecute(iRequest, iResponse);

     final String[] urlParts = iRequest.url.substring(1).split("/");
     if (urlParts.length < 2)
       throw new OHttpRequestException("Syntax error in URL. Expected is: <command>/<database>[/...]");

     iRequest.databaseName = urlParts[1];
     final List<String> authenticationParts = iRequest.authorization != null ? OStringSerializerHelper.split(iRequest.authorization,
         ':') : null;

     OHttpSession currentSession;
     if (iRequest.sessionId != null && iRequest.sessionId.length() > 1) {
       currentSession = OHttpSessionManager.getInstance().getSession(iRequest.sessionId);
       if (currentSession != null && authenticationParts != null) {
         if (!currentSession.getUserName().equals(authenticationParts.get(0))) {
           // CHANGED USER, INVALIDATE THE SESSION
           currentSession = null;
         }
       }
     } else
       currentSession = null;

     if (currentSession == null) {
       // NO SESSION
       if (iRequest.authorization == null || SESSIONID_LOGOUT.equals(iRequest.sessionId)) {
         iResponse.setSessionId(SESSIONID_UNAUTHORIZED);
         sendAuthorizationRequest(iRequest, iResponse, iRequest.databaseName);
         return false;
       } else
         return authenticate(iRequest, iResponse, authenticationParts, iRequest.databaseName);

     } else {
       // CHECK THE SESSION VALIDITY
       if (!currentSession.getDatabaseName().equals(iRequest.databaseName)) {

         // SECURITY PROBLEM: CROSS DATABASE REQUEST!
         OLogManager.instance().warn(this,
             "Session %s is trying to access to the database '%s', but has been authenticated against the database '%s'",
             iRequest.sessionId, iRequest.databaseName, currentSession.getDatabaseName());
         OHttpSessionManager.getInstance().removeSession(iRequest.sessionId);
         sendAuthorizationRequest(iRequest, iResponse, iRequest.databaseName);
         return false;

       } else if (authenticationParts != null && !currentSession.getUserName().equals(authenticationParts.get(0))) {

         // SECURITY PROBLEM: CROSS DATABASE REQUEST!
         OLogManager.instance().warn(this,
             "Session %s is trying to access to the database '%s' with user '%s', but has been authenticated with user '%s'",
             iRequest.sessionId, iRequest.databaseName, authenticationParts.get(0), currentSession.getUserName());
         OHttpSessionManager.getInstance().removeSession(iRequest.sessionId);
         sendAuthorizationRequest(iRequest, iResponse, iRequest.databaseName);
         return false;
       }

       return true;
     }
   }

   @Override
   public boolean afterExecute(final OHttpRequest iRequest, OHttpResponse iResponse) throws IOException {
     ODatabaseRecordThreadLocal.INSTANCE.remove();
     return true;
   }

   protected boolean authenticate(final OHttpRequest iRequest, final OHttpResponse iResponse,
       final List<String> iAuthenticationParts, final String iDatabaseName) throws IOException {
     ODatabaseDocumentTx db = null;
     try {
       db = (ODatabaseDocumentTx) server.openDatabase("document", iDatabaseName, iAuthenticationParts.get(0),
           iAuthenticationParts.get(1));
       // if (db.getUser() == null)
       // // MAYBE A PREVIOUS ROOT REALM? UN AUTHORIZE
       // return false;

       // Set user rid after authentication
       iRequest.data.currentUserId = db.getUser() == null ? "<server user>" : db.getUser().getDocument().getIdentity().toString();

       // AUTHENTICATED: CREATE THE SESSION
       iRequest.sessionId = OHttpSessionManager.getInstance().createSession(iDatabaseName, iAuthenticationParts.get(0),
           iAuthenticationParts.get(1));
       iResponse.sessionId = iRequest.sessionId;
       return true;

     } catch (OSecurityAccessException e) {
       // WRONG USER/PASSWD
     } catch (OLockException e) {
       OLogManager.instance().error(this, "Cannot access to the database '" + iDatabaseName + "'", ODatabaseException.class, e);
     } finally {
       if (db == null) {
           // WRONG USER/PASSWD
           sendAuthorizationRequest(iRequest, iResponse, iDatabaseName);
       }
       else {
           db.close();
       }
     }
     return false;
   }

   protected void sendAuthorizationRequest(final OHttpRequest iRequest, final OHttpResponse iResponse, final String iDatabaseName)
       throws IOException {
     // UNAUTHORIZED
     iRequest.sessionId = SESSIONID_UNAUTHORIZED;
     String header = null;
     if (iRequest.authentication == null || iRequest.authentication.equalsIgnoreCase("basic")) {
       header = "WWW-Authenticate: Basic realm=\"OrientDB db-" + iDatabaseName + "\"";
     }
     iResponse.send(OHttpUtils.STATUS_AUTH_CODE, OHttpUtils.STATUS_AUTH_DESCRIPTION, OHttpUtils.CONTENT_TEXT_PLAIN,
         "401 Unauthorized.", header, false);
   }

   protected ODatabaseDocumentTx getProfiledDatabaseInstance(final OHttpRequest iRequest) throws InterruptedException {
     final OHttpSession session = OHttpSessionManager.getInstance().getSession(iRequest.sessionId);

     if (session == null)
       throw new OSecurityAccessException(iRequest.databaseName, "No session active");

     // after authentication, if current login user is different compare with current DB user, reset DB user to login user
     ODatabaseRecordInternal localDatabase = ODatabaseRecordThreadLocal.INSTANCE.getIfDefined();

     if (localDatabase == null) {
       localDatabase = (ODatabaseDocumentTx) server.openDatabase("document", iRequest.databaseName, session.getUserName(),
           session.getUserPassword());
     } else {

       String currentUserId = iRequest.data.currentUserId;
       if (currentUserId != null && currentUserId.length() > 0 && localDatabase != null && localDatabase.getUser() != null) {
         if (!currentUserId.equals(localDatabase.getUser().getDocument().getIdentity().toString())) {
           ODocument userDoc = localDatabase.load(new ORecordId(currentUserId));
           localDatabase.setUser(new OUser(userDoc));
         }
       }
     }

     iRequest.data.lastDatabase = localDatabase.getName();
     iRequest.data.lastUser = localDatabase.getUser() != null ? localDatabase.getUser().getName() : null;
     return (ODatabaseDocumentTx) localDatabase.getDatabaseOwner();
   }
}
TOP

Related Classes of com.orientechnologies.orient.server.network.protocol.http.command.OServerCommandAuthenticatedDbAbstract

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.