Multiple Secure Client Example

Error formatting macro: composition-setup: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil

In a client/server installation with security, you can create multiple, secure connections to your servers from a single client. The most common use case is a GemFire client embedded in an application server that supports data requests from many users. Each user can be authorized to access a subset of data on the servers. For example, customer users may be allowed to see and update only their own orders and shipments. You create the multiple user connections from the single ClientCache instance in your client application. Each user provides its own credentials, and accesses the servers at its own individual authorization level. Read more about clients with multiple secure users.

Running the Example

This example shows a very simple client/server that uses multiuser authentication in the client. The server listens on a port for client requests and updates. The client does put and get on the server on behalf of multiple users with different credentials. This client uses the valid username and password.

To run this example, you must have terminal sessions configured for the QuickStart examples, as described in Setting Up the Environment.
  1. In one session, start the server:
    $ java quickstart.MultiuserSecurityServer
    
  2. In the other session start the client:
    $ java quickstart.MultiuserSecurityClient
    
  3. Follow the instructions on the screens. You can run the client multiple times trying different operations. Once you are done and the client has exited, press Enter to stop the server.

Example Listings

Program and cache configuration file listings for the client and the server:

Error formatting macro: deck: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
<?xml version="1.0"?>

<!-- MultiuserSecurityServer.xml -->

<!DOCTYPE cache PUBLIC
  "-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
  "http://www.gemstone.com/dtd/cache6_5.dtd">
<cache>
  <cache-server port="40404" maximum-time-between-pings="20000"/>
   <region name="exampleRegion">
      <region-attributes scope="distributed-ack" data-policy="replicate">
      </region-attributes>
  </region>
  <region name="functionServiceExampleRegion">
      <region-attributes data-policy="partition">
      </region-attributes>
  </region>
</cache>
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
package quickstart;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.Region;

/**
 * In this example the server starts on a port with security properties for
 * client requests. Please refer to the quickstart guide for instructions on how
 * to run this example.
 * 
 * Add $GEMFIRE/lib/gfSecurityImpl.jar to your CLASSPATH before running this
 * example.
 * 
 * @author GemStone Systems, Inc
 * 
 * @since 6.5
 */
public class MultiuserSecurityServer {
  public static void main(String[] args) throws Exception {

    if (args.length != 0) {
      System.err.println("Usage: java  quickstart.MultiuserSecurityServer");
      System.exit(1);
    }
    System.out
        .println("\nThis example demonstrates Security functionalities.\n"
            + "This program is a server, listening on a port for client requests.\n"
            + "The client in this example is configured with security properties.");

    System.out.println("Setting security properties for server");
    System.out.println("\nConnecting to the distributed system "
        + "and creating the cache.");

    // Create the cache which causes the cache-xml-file to be parsed
    Cache cache = new CacheFactory()
      .set("name", "SecurityServer")
      .set("cache-xml-file", "xml/MultiuserSecurityServer.xml")
      .set("security-client-accessor",
           "templates.security.DummyAuthorization.create")
      .set("security-client-accessor-pp",
           "templates.security.DummyAuthorization.create")
      .set("security-client-authenticator",
           "templates.security.DummyAuthenticator.create")
      .create();

    // Get the exampleRegion which is a root region
    Region exampleRegion = cache.getRegion("exampleRegion");
    if (exampleRegion == null) {
      System.out
          .println("The region exampleRegion could not be created in cache.");
      return;
    }
    System.out.println("Example region, " + exampleRegion.getFullPath()
        + ", created in cache.");

      Region functionServiceExampleRegion = cache
        .getRegion("functionServiceExampleRegion");
    if (functionServiceExampleRegion == null) {
      System.out.println("The region functionServiceExampleRegion "
          + "could not be created in cache.");
      return;
    }
    for (int i = 0; i < 20; i++) {
      functionServiceExampleRegion.put("KEY_" + i, "VALUE_" + i);
    }
    System.out.println("Example region, "
        + functionServiceExampleRegion.getFullPath()
        + ", created in cache and populated.");

    System.out.println("\nPlease start the security client "
        + "and press Enter when the client finishes all the operations.\n");
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
        System.in));
    bufferedReader.readLine();

    // Close the cache and disconnect from GemFire distributed system
    System.out.println("Closing the cache and disconnecting.");
    cache.close();
    System.out.println("Closed the Server Cache");
  }
}
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
<?xml version="1.0"?>
<!-- MultiuserSecurityClient.xml
     Configures a region as a client region in a Security cache. The 
     region's pool connects to a server listening on port 40404.
-->
<!DOCTYPE client-cache PUBLIC
  "-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
  "http://www.gemstone.com/dtd/cache6_5.dtd">
<client-cache>
  <pool name="multiuserClient" subscription-enabled="true" multiuser-authentication="true">
    <server host="localhost" port="40404"/>
  </pool>
  <region name="exampleRegion" refid="PROXY"/>
  <region name="functionServiceExampleRegion" refid="PROXY"/>
</client-cache>
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
package quickstart;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.ServerOperationException;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionException;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.cache.execute.ResultCollector;
import com.gemstone.gemfire.cache.query.CqAttributes;
import com.gemstone.gemfire.cache.query.CqAttributesFactory;
import com.gemstone.gemfire.cache.query.CqListener;
import com.gemstone.gemfire.cache.query.CqQuery;
import com.gemstone.gemfire.cache.query.QueryService;
import com.gemstone.gemfire.security.NotAuthorizedException;

/**
 * In this example of secure client, the server listens on a port for client
 * requests and updates. The client does put and get on the server on behalf of
 * multiple users with different credentials. This client uses the valid
 * username and password. Please refer to the quickstart guide for instructions
 * on how to run this example.
 * 
 * Add $GEMFIRE/lib/gfSecurityImpl.jar to your CLASSPATH before running this
 * example.
 * 
 * @author GemStone Systems, Inc
 * @since 6.5
 * 
 */
public class MultiuserSecurityClient {

  public static void main(String[] args) throws Exception {
    if (args.length > 0) {
      System.err.println("\n   Usage: java quickstart.MultiuserSecurityClient");
      System.exit(1);
    }

    System.out.println("Please select your option.");
    System.out.println(" Enter 1 for put and get operations.");
    System.out.println(" Enter 2 for executing functions.");
    System.out.println(" Enter 3 for executing Continuous Query (CQs).");
    System.out.println(" Your selection: ");
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
        System.in));

    int operation = 0;
    String input = "";
    try {
      input = bufferedReader.readLine();
      operation = Integer.parseInt(input);
    } catch (NumberFormatException nfe) {
      System.out.println("Invalid selection: " + input);
      System.exit(1);
    }
    if (operation < 1 || operation > 3) {
      System.out.println("Invalid selection: " + operation);
      System.exit(1);
    }

    System.out.println("-----------------------------------------------------");

    System.out.println("Setting security properties for client...");

    // Create and configure the client cache
    ClientCache cache = new ClientCacheFactory()
      .set("name", "SecurityClient")
      .set("cache-xml-file", "xml/MultiuserSecurityClient.xml")
      .set("security-client-auth-init",
           "templates.security.UserPasswordAuthInit.create")
      .create();

    String[] usernames;
    String[] passwords;
 
    switch (operation) {
      case 1:
        // writer0 is not authorized to do a GET operation but a PUT operation.
        // reader1 is not authorized to do a PUT operation but a GET operation.
        System.out
            .println("-----------------------------------------------------");
        System.out.println("User 'writer0' "
            + "is authorized to do a PUT operation, but not a GET operation.");
        System.out.println("User 'reader1' "
            + "is authorized to do a GET operation, but not a PUT operation.");
        System.out
            .println("-----------------------------------------------------");
        pressEnterToContinue();
        usernames = new String[] {"writer0", "reader1"};
        passwords = new String[] {"writer0", "reader1"};
        for (int i = 0; i < usernames.length; i++) {
          final String username = usernames[i];
          final String password = passwords[i];
          doOps(cache, username, password);
          pressEnterToContinue();
        }
        break;
      case 2:
        // writer0 is not authorized to do a EXECUTE_FUNCTION operation.
        // reader1 is authorized to do a EXECUTE_FUCTION operation.
        System.out
            .println("-----------------------------------------------------");
        System.out.println("User 'writer0' "
            + "is not authorized to perform EXECUTE_FUNCTION operations.");
        System.out.println("User 'reader1' "
            + "is authorized to do EXECUTE_FUNCTION operations.");
        System.out
            .println("-----------------------------------------------------");
        pressEnterToContinue();
        usernames = new String[] {"writer0", "reader1"};
        passwords = new String[] {"writer0", "reader1"};

        for (int i = 0; i < usernames.length; i++) {
          final String username = usernames[i];
          final String password = passwords[i];
          doFunctionExecute(cache, username, password);
          pressEnterToContinue();
        }
        break;
      case 3:
        doCq(cache);
        break;
      default:
        System.out.println("Invalid option: " + operation);
        break;
    }

    System.out.println("\nMultiuserSecurityClient closed.");
    System.out.println("-----------------------------------------------------");
  }

  private static void doOps(ClientCache cache, String username, String password)
      throws Exception {
    Properties properties = new Properties();
    properties.setProperty("security-username", username);
    properties.setProperty("security-password", password);

    RegionService regionService = cache.createAuthenticatedView(properties);
    Region userRegion = regionService.getRegion("exampleRegion");
    if (userRegion == null) {
      System.out.println("[" + username + "] "
          + "The region exampleRegion could not be created in the cache.");
      return;
    }
    System.out.println("\n[" + username + "] Performing put and get operations...");
    System.out.println("[" + username + "] Putting values in the cache...");
    Thread.sleep(500);
    Object key = null;
    Object value = null;
    try {
      for (int j = 1; j < 3; j++) {
        key = "key" + j;
        value = "value" + j;
        System.out.println("[" + username + "] Putting entry: " + key + ", "
            + value);
        Thread.sleep(500);
        userRegion.put(key, value);
      }
    } catch (ServerOperationException soe) {
      NotAuthorizedException nae = (NotAuthorizedException)soe.getCause();
      System.out.println("[" + username
          + "] Got expected NotAuthorizedException: " + nae.getMessage());
    }

    try {
      System.out.println("[" + username + "] Getting entry: key1");
      value = userRegion.get("key1");
      Thread.sleep(500);
      System.out.println("[" + username + "] Got value for key1: " + value);
    } catch (ServerOperationException soe) {
      NotAuthorizedException nae = (NotAuthorizedException)soe.getCause();
      System.out.println("[" + username
          + "] Got expected NotAuthorizedException: " + nae.getMessage());
    }
    regionService.close();
    System.out.println("[" + username + "] Closed the cache for this user.");
    Thread.sleep(500);
  }

  private static void doFunctionExecute(ClientCache cache, String username,
      String password) throws Exception {
    Properties properties = new Properties();
    properties.setProperty("security-username", username);
    properties.setProperty("security-password", password);
    
    RegionService regionService = cache.createAuthenticatedView(properties);
    Region userRegion = regionService.getRegion("functionServiceExampleRegion");
    if (userRegion == null) {
      System.out.println("[" + username
          + "] The region functionServiceExampleRegion "
          + "could not be created in the cache.");
      return;
    }
    try {
      MultiGetFunction function = new MultiGetFunction();
      FunctionService.registerFunction(function);
      Set<String> keysForGet = new HashSet<String>();
      keysForGet.add("KEY_4");
      keysForGet.add("KEY_9");
      keysForGet.add("KEY_7");

      Execution execution = FunctionService.onRegion(userRegion).withFilter(
          keysForGet).withArgs(Boolean.FALSE).withCollector(
          new MyArrayListResultCollector());
      System.out.println("\n[" + username + "] Executing function on region...");
      ResultCollector rcRegion = execution.execute(function);
      System.out.println("[" + username
          + "] Function executed, now getting the result...");
      Thread.sleep(500);
      List resultRegion = (List)rcRegion.getResult();
      System.out.println("[" + username + "] Got result with size "
          + resultRegion.size() + ".");
    }
    catch (FunctionException ex) {
      if ((ex.getCause() instanceof ServerOperationException && (ex.getCause())
          .getCause() instanceof NotAuthorizedException)) {
        System.out.println("[" + username
            + "] Got expected NotAuthorizedException: "
            + ex.getCause().getCause());
      }
    }
    try {
      MultiGetFunction function = new MultiGetFunction();
      Execution execution = FunctionService.onServer(regionService)
          .withCollector(new MyArrayListResultCollector());
      System.out.println("[" + username + "] Executing function on server...");
      ResultCollector rcServer = execution.execute(function);
      System.out.println("[" + username
          + "] Function executed, now getting the result...");
      Thread.sleep(500);
      List resultServer = (List)rcServer.getResult();
      System.out.println("[" + username + "] Got result with size "
          + resultServer.size() + ".");

      Thread.sleep(500);
    }
    catch (ServerOperationException soe) {
      if (soe.getCause() instanceof NotAuthorizedException) {
        System.out.println("[" + username
            + "] Got expected NotAuthorizedException: " + soe.getCause());
      }
    }
    regionService.close();
    System.out.println("[" + username + "] Closed the cache for this user.");
    Thread.sleep(500);
  }

  public static void doCq(ClientCache cache) throws Exception {
    Properties properties = new Properties();
    properties.setProperty("security-username", "root");
    properties.setProperty("security-password", "root");
    RegionService regionService1 = cache.createAuthenticatedView(properties);

    properties = new Properties();
    properties.setProperty("security-username", "root");
    properties.setProperty("security-password", "root");
    RegionService regionService2 = cache.createAuthenticatedView(properties);

    properties = new Properties();
    properties.setProperty("security-username", "reader1");
    properties.setProperty("security-password", "reader1");
    RegionService regionService3 = cache.createAuthenticatedView(properties);

    QueryService queryService1 = regionService1.getQueryService();
    QueryService queryService2 = regionService2.getQueryService();
    QueryService queryService3 = regionService3.getQueryService();

    Region exampleRegion = regionService1.getRegion("exampleRegion");

    // Create CQ Attributes.
    CqAttributesFactory cqAf = new CqAttributesFactory();

    // Construct a new CQ for each user.
    String userOneCqName = "CQ_1";
    String userOneQuery = "SELECT * FROM /exampleRegion e "
        + "where e='VALUE_1' OR e='VALUE_3'";
    System.out.println("User 1 executing CQ \"" + userOneCqName
        + "\" with query ");
    System.out.println("    \"" + userOneQuery + "\"");
    // Initialize and set CqListener for first user.
    CqListener[] cqListeners = {new SimpleCqListener("User 1")};
    cqAf.initCqListeners(cqListeners);
    CqAttributes cqa = cqAf.create();
    // Execute the Cq for first user. This registers the cq on the server.
    CqQuery cq1 = queryService1.newCq(userOneCqName, userOneQuery, cqa);
    cq1.execute();

    String userTwoCqName = "CQ_2";
    String userTwoQuery = "SELECT * FROM /exampleRegion e "
        + "where e='VALUE_2' OR e='VALUE_3'";
    System.out.println("User 2 executing CQ \"" + userTwoCqName
        + "\" with query ");
    System.out.println("    \"" + userTwoQuery + "\"");
    // Initialize and set CqListener for second user.
    cqListeners[0] = new SimpleCqListener("User 2");
    cqAf.initCqListeners(cqListeners);
    cqa = cqAf.create();
    // Execute the Cq for second user. This registers the cq on the server.
    CqQuery cq2 = queryService2.newCq(userTwoCqName, userTwoQuery, cqa);
    cq2.execute();

    String userThreeCqName = "CQ_3";
    String userThreeQuery = "SELECT * FROM /exampleRegion";
    // The User 3 is not authorized to receive CQ events from server.
    System.out.println("User 3 executing CQ \"" + userThreeCqName
        + "\" with query ");
    System.out.println("    \"" + userThreeQuery + "\"");
    // Initialize and set CqListener for third user.
    cqListeners[0] = new SimpleCqListener("User 3");
    cqAf.initCqListeners(cqListeners);
    cqa = cqAf.create();
    // Execute the Cq for third user. This registers the cq on the server.
    CqQuery cq3 = queryService3.newCq(userThreeCqName, userThreeQuery, cqa);
    cq3.execute();

    System.out.println("-----------------------------------------------------");
    System.out.println("'User 1' and 'User 2' "
        + "are authorized to receive CQ events.");
    System.out.println("'User 3' is not authorized receive CQ events.");
    System.out.println("-----------------------------------------------------");

    System.out.println("\nThis client will update the server cache and its CQ "
        + "listeners will get events\nfor any changes to the CQ result set. "
        + "CQ events provide the base operation (change\nin the server's "
        + "cache), and the query operation (change in the CQ's result set).");
    pressEnterToContinue();

    // Create a new value in the cache
    System.out.println("_____________________________________________________");
    System.out.println("Putting key1 with value 'VALUE_1'\n"
        + "This satisfies the query for User 1, so its CqListener "
        + "will report a query create\n" + "event from the server cache.");
    exampleRegion.put("key1", "VALUE_1");

    // Wait for the events to come through so the screen output makes sense
    Thread.sleep(2000);
    pressEnterToContinue();

    // Update value.
    System.out.println("_____________________________________________________");
    System.out.println("Updating key1 with value 'VALUE_2'\n"
        + "This satisfies the query for User 2, so its CqListener "
        + "will report a query create\n"
        + "event from the server cache. The CqListener for User 1 "
        + "will report a query destroy event.");
    exampleRegion.put("key1", "VALUE_2");
    Thread.sleep(2000);
    pressEnterToContinue();

    // Update value.
    System.out.println("_____________________________________________________");
    System.out.println("Updating key1 with value 'VALUE_3'\n"
        + "This adds key1 back into the CQ result set for User 1, "
        + "so its CqListener will\n"
        + "report a query create event. The CqListener for User 2 will "
        + "report a query update event.");
    exampleRegion.put("key1", "VALUE_3");
    Thread.sleep(2000);
    pressEnterToContinue();

    // Close cqs for User 1
    System.out.println("_____________________________________________________");
    System.out.println("Closing CQ for User 1.");
    queryService1.closeCqs();
    System.out.println("Now on, CqListener for User 1 will not be invoked.");
    pressEnterToContinue();

    // Destroy value.
    System.out.println("_____________________________________________________");
    System.out.println("Destroying key1.\n"
        + "This removes key1 from the CQ result set, "
        + "so the CqListener will report a query destroy event.");
    exampleRegion.destroy("key1");
    Thread.sleep(2000);
    pressEnterToContinue();

    // Close the cache and disconnect from GemFire distributed system
    System.out.println("Closing the cache for all users...");
    regionService1.close();
    regionService2.close();
    regionService3.close();
  }
  
  public static void pressEnterToContinue() throws IOException {
    System.out.println("Press Enter to continue.");
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
        System.in));
    bufferedReader.readLine();
  }
}
Error formatting macro: card: java.lang.NoClassDefFoundError: net/customware/confluence/plugin/composition/CompositionUtil
package quickstart;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.gemstone.gemfire.cache.server.CacheServer;
import com.gemstone.gemfire.cache.execute.FunctionAdapter;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;

/**
 * Application Function to retrieve values for multiple keys in a region
 * 
 * @author Gemstone Systems Inc
 * @since 6.0
 * 
 */
public class MultiGetFunction extends FunctionAdapter {

  public void execute(FunctionContext fc) {
    if(fc instanceof RegionFunctionContext){
    RegionFunctionContext context = (RegionFunctionContext)fc;
    Set keys = context.getFilter();
    Set keysTillSecondLast = new HashSet();
    int setSize = keys.size();
    Iterator keysIterator = keys.iterator();
    for (int i = 0; i < (setSize - 1); i++) {
      keysTillSecondLast.add(keysIterator.next());
    }
    for (Object k : keysTillSecondLast) {
      context.getResultSender().sendResult(
          (Serializable)PartitionRegionHelper.getLocalDataForContext(context)
              .get(k));
    }
    Object lastResult = keysIterator.next();
    context.getResultSender().lastResult(
        (Serializable)PartitionRegionHelper.getLocalDataForContext(context)
            .get(lastResult));
    }else {
      fc.getResultSender().lastResult(Runtime.getRuntime().freeMemory()/(1024*1024)); 
    }
  }

  public String getId() {
    return getClass().getName();
  }
}

Related Javadocs

Security package

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.