RestorableJDBCVisa.java 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * Licensed Materials - Property of IBM
  3. *
  4. * IBM Cognos Products: CAMAAA
  5. *
  6. * (C) Copyright IBM Corp. 2012
  7. *
  8. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. */
  10. import java.io.Externalizable;
  11. import java.io.IOException;
  12. import java.io.ObjectInput;
  13. import java.io.ObjectOutput;
  14. import java.sql.SQLException;
  15. import com.cognos.CAM_AAA.authentication.IAccount;
  16. import com.cognos.CAM_AAA.authentication.IBiBusHeader;
  17. import com.cognos.CAM_AAA.authentication.ICredential;
  18. import com.cognos.CAM_AAA.authentication.IRestorableVisa;
  19. import com.cognos.CAM_AAA.authentication.ITrustedCredential;
  20. import com.cognos.CAM_AAA.authentication.ReadOnlyDisplayObject;
  21. import com.cognos.CAM_AAA.authentication.SystemRecoverableException;
  22. import com.cognos.CAM_AAA.authentication.TextNoEchoDisplayObject;
  23. import com.cognos.CAM_AAA.authentication.UnrecoverableException;
  24. import com.cognos.CAM_AAA.authentication.UserRecoverableException;
  25. /**
  26. * This is a modified version of {@link JDBCVisa} that supports the {@link IRestorableVisa}
  27. * interfaces. This allows the session to be restored on failover.
  28. *
  29. */
  30. public class RestorableJDBCVisa extends Visa implements IRestorableVisa
  31. {
  32. // This flag should be true if the state information changes. The cognos
  33. // server will update it's cached copy of this visa when true.
  34. private boolean hasChanged = false;
  35. private Account account = null;
  36. private String username;
  37. private String password;
  38. /**
  39. * Initializes this visa
  40. */
  41. public void init(String username, String password) throws UnrecoverableException
  42. {
  43. try
  44. {
  45. ConnectionManager connectionManager = ConnectionManager.get();
  46. // Create account object for the user.
  47. account = QueryUtil.createAccount(connectionManager, username, password);
  48. QueryUtil.updateMembership(connectionManager, this);
  49. this.username = username;
  50. this.password = password;
  51. // This is very important. You must flag this Visa as changed whenever it's state (i.e. credentials)
  52. // is modified
  53. hasChanged = true;
  54. }
  55. catch (final SQLException e)
  56. {
  57. throw new UnrecoverableException("Connection Error", "Database connection failure. Reason: "
  58. + ConnectionManager.getSqlExceptionDetails(e));
  59. }
  60. }
  61. @Override
  62. public ITrustedCredential generateTrustedCredential(IBiBusHeader theAuthRequest) throws UserRecoverableException,
  63. SystemRecoverableException, UnrecoverableException
  64. {
  65. // 1 - Look for credentials coming from SDK request
  66. JDBCSample.Credential credential = JDBCSample.getCredentialValues(theAuthRequest);
  67. if (credential.isEmpty())
  68. {
  69. // 2 - Look for credentials in formfield
  70. credential = JDBCSample.getFormFieldValues(theAuthRequest);
  71. }
  72. if (credential.isEmpty() || !credential.getUsername().equals(username))
  73. {
  74. credential.setUsername(username);
  75. credential.setPassword(password);
  76. }
  77. if (!validateConnection(credential))
  78. {
  79. final UserRecoverableException e =
  80. new UserRecoverableException("Please type your credentials for authentication.",
  81. "The provided credentials are invalid.");
  82. e.addDisplayObject(new ReadOnlyDisplayObject("User ID:", "CAMUsername", this.username));
  83. e.addDisplayObject(new TextNoEchoDisplayObject("Password:", "CAMPassword"));
  84. throw e;
  85. }
  86. final TrustedCredential tc = new TrustedCredential();
  87. tc.addCredentialValue("username", this.username);
  88. tc.addCredentialValue("password", this.password);
  89. return tc;
  90. }
  91. @Override
  92. public ICredential generateCredential(IBiBusHeader theBiBusHeader) throws UserRecoverableException, SystemRecoverableException,
  93. UnrecoverableException
  94. {
  95. if (!this.validateConnection(this.username, this.password))
  96. {
  97. final UnrecoverableException e =
  98. new UnrecoverableException("Could not generate credentials for the user.", "Visa contains invalid credentials.");
  99. throw e;
  100. }
  101. final Credential credentials = new Credential();
  102. credentials.addCredentialValue("username", this.username);
  103. credentials.addCredentialValue("password", this.password);
  104. return credentials;
  105. }
  106. @Override
  107. public IAccount getAccount()
  108. {
  109. return account;
  110. }
  111. /**
  112. * Validates the credentials against the database
  113. */
  114. private boolean validateConnection(final JDBCSample.Credential credential)
  115. {
  116. return validateConnection(credential.getUsername(), credential.getPassword());
  117. }
  118. /**
  119. * Validates the credentials against the database
  120. */
  121. private boolean validateConnection(final String theUsername, final String thePassword)
  122. {
  123. try
  124. {
  125. QueryUtil.createAccount(ConnectionManager.get(), theUsername, thePassword);
  126. username = theUsername;
  127. password = thePassword;
  128. }
  129. catch (UnrecoverableException ex)
  130. {
  131. return false;
  132. }
  133. return true;
  134. }
  135. /**
  136. * To be able to restore on failover, we need to externalize this Visa. In this
  137. * case, the only pieces of info we need to recreate the Visa is the username
  138. * and password
  139. *
  140. * For simplicity, we'll externalize them in plain-text. For your implementation, you should
  141. * encrypt the credentials on the way out.
  142. *
  143. * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
  144. */
  145. public void writeExternal(ObjectOutput out) throws IOException
  146. {
  147. out.writeUTF(username);
  148. out.writeUTF(password);
  149. }
  150. /**
  151. * In a failover scenario, the new server will try to recreate this Visa.
  152. * We'll just generate a new account from the saved username and password
  153. *
  154. * @see Externalizable#readExternal(ObjectInput)
  155. */
  156. public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
  157. {
  158. try
  159. {
  160. String username = in.readUTF();
  161. String password = in.readUTF();
  162. init(username, password);
  163. }
  164. catch (UnrecoverableException e)
  165. {
  166. throw new IOException(e);
  167. }
  168. }
  169. /* (non-Javadoc)
  170. * @see com.cognos.CAM_AAA.authentication.IRestorableVisa#hasStateChanged()
  171. */
  172. public boolean hasStateChanged()
  173. {
  174. return hasChanged;
  175. }
  176. /* (non-Javadoc)
  177. * @see com.cognos.CAM_AAA.authentication.IRestorableVisa#resetChangeIndicator()
  178. */
  179. public void resetChangeIndicator()
  180. {
  181. hasChanged = false;
  182. }
  183. }