123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- /**
- * Licensed Materials - Property of IBM
- *
- * IBM Cognos Products: CAMAAA
- *
- * (C) Copyright IBM Corp. 2012
- *
- * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
- */
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.sql.SQLException;
- import java.util.Locale;
- import com.cognos.CAM_AAA.authentication.IBiBusHeader;
- import com.cognos.CAM_AAA.authentication.IBiBusHeader2;
- import com.cognos.CAM_AAA.authentication.INamespaceAuthenticationProvider2;
- import com.cognos.CAM_AAA.authentication.INamespaceConfiguration;
- import com.cognos.CAM_AAA.authentication.IQuery;
- import com.cognos.CAM_AAA.authentication.IQueryResult;
- import com.cognos.CAM_AAA.authentication.ISearchExpression;
- import com.cognos.CAM_AAA.authentication.ISearchFilter;
- import com.cognos.CAM_AAA.authentication.ISearchStep;
- import com.cognos.CAM_AAA.authentication.ISearchStep.SearchAxis;
- import com.cognos.CAM_AAA.authentication.IVisa;
- import com.cognos.CAM_AAA.authentication.QueryResult;
- import com.cognos.CAM_AAA.authentication.ReadOnlyDisplayObject;
- import com.cognos.CAM_AAA.authentication.SystemRecoverableException;
- import com.cognos.CAM_AAA.authentication.TextDisplayObject;
- import com.cognos.CAM_AAA.authentication.TextNoEchoDisplayObject;
- import com.cognos.CAM_AAA.authentication.UnrecoverableException;
- import com.cognos.CAM_AAA.authentication.UserRecoverableException;
- /**
- * This is a modified version of the JDBCSample that demonstrates how to implement a custom namespace that can
- * handle failover of the user session.
- *
- * Note that IBM Cognos must be properly configured to support authentication failover for this to work.
- *
- * @See {@link JDBCSample}
- *
- */
- public class RestorableJDBCSample extends Namespace implements INamespaceAuthenticationProvider2
- {
- /**
- * The logon method is virtually identical to {@link JDBCSample#logon(IBiBusHeader2)
- *
- * The main difference is that now we need to use a RestorableJDBCVisa instead of a JDBCVisa.
- * @see INamespaceAuthenticationProvider2#logon(IBiBusHeader2)
- */
- public IVisa logon(IBiBusHeader2 theAuthRequest) throws UserRecoverableException, SystemRecoverableException,
- UnrecoverableException
- {
- RestorableJDBCVisa visa = null;
- ConnectionManager mgr = ConnectionManager.get();
- // 1 - Look for trusted credentials
- JDBCSample.Credential credential = JDBCSample.getTrustedCredentialValues(theAuthRequest);
- if (credential.isEmpty())
- credential = JDBCSample.getCredentialValues(theAuthRequest);
- if (credential.isEmpty())
- credential = JDBCSample.getFormFieldValues(theAuthRequest);
- // here, should be something for the single signon case
- if (credential.isEmpty() && mgr.singleSignOnEnabled())
- credential = JDBCSample.getTrustedEnvironmentVaribleValue(theAuthRequest);
- if (credential.isEmpty() && mgr.singleSignOnEnabled())
- {
- // null implies the provider has to start the dance so throw a SysRecov.
- // the SysRecov needs to have the name of the variable we look for in
- // the second parameter
- SystemRecoverableException e = new SystemRecoverableException("Challenge for REMOTE_USER", "REMOTE_USER");
- throw e;
- }
- if (credential.isEmpty())
- {
- // Assume this is the initial logon and pass null for errorDetails
- generateAndThrowExceptionForLogonPrompt(null);
- }
- try
- {
- //
- // Create a Visa for the new user. Unlike the JDBCVisa, we will not pas a reference to
- // the ConnectionManager. Instead, the Visa will use a static accessor to get the singleton
- // reference to the ConnectionManager
- //
- visa = new RestorableJDBCVisa();
- visa.init(credential.getUsername(), credential.getPassword());
- }
- catch (final UnrecoverableException ex)
- {
- final String errorDetails = RestorableJDBCSample.getErrorDetails(ex);
- // Something went wrong, probably because the user's credentials
- // are invalid.
- generateAndThrowExceptionForLogonPrompt(errorDetails);
- }
- return visa;
- }
- /**
- * This method is implemented the same as in {@link JDBCSample#logoff(IVisa, IBiBusHeader)
- *
- * @see INamespaceAuthenticationProvider2#logoff(IVisa, IBiBusHeader)
- */
- public void logoff(IVisa theVisa, IBiBusHeader theBiBusHeader)
- {
- try
- {
- // We can safely assume that we'll get back the same Visa that we
- // issued.
- final RestorableJDBCVisa visa = (RestorableJDBCVisa) theVisa;
- visa.destroy();
- }
- catch (UnrecoverableException e)
- {
- e.printStackTrace();
- }
- }
- /**
- * The search method only has minor modifications from {@link JDBCSample#search(IVisa, IQuery), as we no longer
- * need to hold a reference to the ConnectionManager and we are using a RestorableJDBCVIsa
- *
- * @see com.cognos.CAM_AAA.authentication.INamespaceAuthenticationProviderBase#search(com.cognos.CAM_AAA.authentication.IVisa, com.cognos.CAM_AAA.authentication.IQuery)
- */
- public IQueryResult search(IVisa theVisa, IQuery theQuery) throws UnrecoverableException
- {
- // We can safely assume that we'll get back the same Visa that we
- // issued.
- final RestorableJDBCVisa visa = (RestorableJDBCVisa) theVisa;
- final QueryResult result = new QueryResult();
- try
- {
- final ISearchExpression expression = theQuery.getSearchExpression();
- final String objectID = expression.getObjectID();
- final ISearchStep[] steps = expression.getSteps();
- // It doesn't make sense to have multiple steps for this provider
- // since the objects are not hierarchical.
- if (steps.length != 1)
- throw new UnrecoverableException("Internal Error",
- "Invalid search expression. Multiple steps is not supported for this namespace.");
- final StringBuffer sqlCondition = new StringBuffer();
- final int searchType = steps[0].getAxis();
- final ISearchFilter filter = steps[0].getPredicate();
- String tenantId = QueryUtil.getTenantId(visa.getAccount());
- switch (searchType)
- {
- case SearchAxis.Self:
- case SearchAxis.DescendentOrSelf:
- if (objectID == null)
- {
- if (filter == null || this.matchesFilter(filter))
- result.addObject(this);
- // Add current namespace
- if (searchType == SearchAxis.Self)
- return result;
- else
- sqlCondition.append(QueryUtil.getSqlCondition(filter));
- }
- else if (objectID.startsWith("u:") && objectID.equals(visa.getAccount().getObjectID()))
- {
- if (filter == null || this.matchesFilter(filter))
- result.addObject(visa.getAccount());
- // Add current user
- return result;
- }
- else if (objectID.startsWith("u:"))
- {
- final String sqlID = objectID.substring(2);
- sqlCondition.append(QueryUtil.getSqlCondition(filter));
- if (sqlCondition.length() > 0)
- sqlCondition.append(" AND ");
- sqlCondition.append("ID = " + sqlID + " AND ISUSER = 1");
- }
- else if (objectID.startsWith("g:"))
- {
- final String sqlID = objectID.substring(2);
- sqlCondition.append(QueryUtil.getSqlCondition(filter));
- if (sqlCondition.length() > 0)
- sqlCondition.append(" AND ");
- sqlCondition.append("ID = " + sqlID + " AND ISGROUP = 1");
- }
- break;
- default:
- sqlCondition.append(QueryUtil.getSqlCondition(filter));
- break;
- }
- sqlCondition.append(getTenantSql(tenantId));
- QueryUtil.searchQuery(ConnectionManager.get(), sqlCondition.toString(), theQuery.getQueryOption(),
- theQuery.getProperties(), theQuery.getSortProperties(), result, this);
- }
- catch (final SQLException e)
- {
- e.printStackTrace();
- }
- catch (final UnrecoverableException e)
- {
- e.printStackTrace();
- }
- return result;
- }
- /**
- * This method requires only minor modifications from {@link JDBCSample#init(INamespaceConfiguration)}, due to the fact
- * that the {@link ConnectionManager} is now a singleton
- *
- * @see Namespace#init(com.cognos.CAM_AAA.authentication.INamespaceConfiguration)
- */
- @Override
- public void init(INamespaceConfiguration theNamespaceConfiguration) throws UnrecoverableException
- {
- try
- {
- super.init(theNamespaceConfiguration);
- addName(theNamespaceConfiguration.getServerLocale(), theNamespaceConfiguration.getDisplayName());
- ConnectionManager.get().init(theNamespaceConfiguration);
- }
- catch (final IOException e)
- {
- throw new UnrecoverableException("Configuration Error", "Provider initialization failure. Reason: " + e.toString());
- }
- catch (final ClassNotFoundException e)
- {
- throw new UnrecoverableException("Configuration Error", "Provider initialization failure. Reason: " + e.toString());
- }
- }
-
- //
- // The following methods require no modification compared to their implementations in JDBCSample.
- //
- private static String getErrorDetails(final UnrecoverableException e)
- {
- final ByteArrayOutputStream out = new ByteArrayOutputStream();
- final PrintStream ps = new PrintStream(out);
- ps.println(e.getClass().getName() + " : ");
- final String[] messages = e.getMessages();
- for (int i = 0; i < messages.length; i++)
- ps.println(messages[i]);
- ps.println();
- e.printStackTrace(ps);
- ps.close();
- return out.toString();
- }
- private static String getTenantSql(String tenantId)
- {
- return " AND (TENANT='' OR TENANT='" + tenantId + "'" + ")";
- }
- /*
- * Generate an exception with applicable display objects for the login prompt Note: If this is the initial logon, to avoid an
- * empty logon log, be sure to throw either: a) a UserRecoverableException with null errorDetails b) a
- * SystemRecoverableException
- */
- private void generateAndThrowExceptionForLogonPrompt(String errorDetails) throws UserRecoverableException
- {
- final UserRecoverableException e =
- new UserRecoverableException("Please type your credentials for authentication.", errorDetails);
- e.addDisplayObject(new ReadOnlyDisplayObject("Namespace:", "CAMNamespaceDisplayName", this.getName(Locale.getDefault())));
- e.addDisplayObject(new TextDisplayObject("User ID:", "CAMUsername"));
- e.addDisplayObject(new TextNoEchoDisplayObject("Password:", "CAMPassword"));
- throw e;
- }
- }
|