PageRenderTime 58ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/main/java/org/apache/ki/mgt/AbstractRememberMeManager.java

https://github.com/apache/jsecurity
Java | 283 lines | 185 code | 49 blank | 49 comment | 18 complexity | a3aec6daecab4b5faaab5818ea899c13 MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package org.apache.ki.mgt;
  20. import org.slf4j.Logger;
  21. import org.slf4j.LoggerFactory;
  22. import org.apache.ki.authc.AuthenticationException;
  23. import org.apache.ki.authc.AuthenticationInfo;
  24. import org.apache.ki.authc.AuthenticationToken;
  25. import org.apache.ki.authc.RememberMeAuthenticationToken;
  26. import org.apache.ki.codec.Base64;
  27. import org.apache.ki.codec.Hex;
  28. import org.apache.ki.crypto.BlowfishCipher;
  29. import org.apache.ki.crypto.Cipher;
  30. import org.apache.ki.io.DefaultSerializer;
  31. import org.apache.ki.io.SerializationException;
  32. import org.apache.ki.io.Serializer;
  33. import org.apache.ki.subject.PrincipalCollection;
  34. /**
  35. * Abstract implementation of the <code>RememberMeManager</code> interface that handles
  36. * {@link #setSerializer(org.apache.ki.io.Serializer) serialization} and
  37. * {@link #setCipher(org.apache.ki.crypto.Cipher) encryption} of the remembered user identity.
  38. * <p/>
  39. * The remembered identity storage location is implementation-specific.
  40. *
  41. * @author Les Hazlewood
  42. * @author Jeremy Haile
  43. * @since 0.9
  44. */
  45. public abstract class AbstractRememberMeManager implements RememberMeManager {
  46. //TODO - complete JavaDoc
  47. /**
  48. * private inner log instance.
  49. */
  50. private static final Logger log = LoggerFactory.getLogger(AbstractRememberMeManager.class);
  51. private Serializer serializer = new DefaultSerializer();
  52. private Cipher cipher = new BlowfishCipher();
  53. private byte[] encryptionCipherKey = null;
  54. private byte[] decryptionCipherKey = null;
  55. public AbstractRememberMeManager() {
  56. }
  57. public Serializer getSerializer() {
  58. return serializer;
  59. }
  60. public void setSerializer(Serializer serializer) {
  61. this.serializer = serializer;
  62. }
  63. public Cipher getCipher() {
  64. return cipher;
  65. }
  66. public void setCipher(Cipher cipher) {
  67. this.cipher = cipher;
  68. }
  69. public byte[] getEncryptionCipherKey() {
  70. return encryptionCipherKey;
  71. }
  72. public void setEncryptionCipherKey(byte[] encryptionCipherKey) {
  73. this.encryptionCipherKey = encryptionCipherKey;
  74. }
  75. public void setEncryptionCipherKeyHex(String hex) {
  76. setEncryptionCipherKey(Hex.decode(hex));
  77. }
  78. public void setEncryptionCipherKeyBase64(String base64) {
  79. setEncryptionCipherKey(Base64.decode(base64));
  80. }
  81. public byte[] getDecryptionCipherKey() {
  82. return decryptionCipherKey;
  83. }
  84. public void setDecryptionCipherKey(byte[] decryptionCipherKey) {
  85. this.decryptionCipherKey = decryptionCipherKey;
  86. }
  87. public void setDecryptionCipherKeyHex(String hex) {
  88. setDecryptionCipherKey(Hex.decode(hex));
  89. }
  90. public void setDecryptionCipherKeyBase64(String base64) {
  91. setDecryptionCipherKey(Base64.decode(base64));
  92. }
  93. public byte[] getCipherKey() {
  94. //Since this method should only be used with symmetric ciphers
  95. //(where the enc and dec keys are the same), either is fine, just return one of them:
  96. return getEncryptionCipherKey();
  97. }
  98. public void setCipherKey(byte[] cipherKey) {
  99. //Since this method should only be used in symmetric ciphers
  100. //(where the enc and dec keys are the same), set it on both:
  101. setEncryptionCipherKey(cipherKey);
  102. setDecryptionCipherKey(cipherKey);
  103. }
  104. public void setCipherKeyHex(String hex) {
  105. setCipherKey(Hex.decode(hex));
  106. }
  107. public void setCipherKeyBase64(String base64) {
  108. setCipherKey(Base64.decode(base64));
  109. }
  110. // Abstract methods to be implemented by subclasses
  111. protected abstract void rememberSerializedIdentity(byte[] serialized);
  112. protected abstract byte[] getSerializedRememberedIdentity();
  113. protected abstract void forgetIdentity();
  114. protected boolean isRememberMe(AuthenticationToken token) {
  115. return token != null && (token instanceof RememberMeAuthenticationToken) &&
  116. ((RememberMeAuthenticationToken) token).isRememberMe();
  117. }
  118. public void onSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info) {
  119. //always clear any previous identity:
  120. forgetIdentity(token);
  121. //reset it if necessary:
  122. if (isRememberMe(token)) {
  123. rememberIdentity(token, info);
  124. } else {
  125. if (log.isDebugEnabled()) {
  126. log.debug("AuthenticationToken did not indicate RememberMe is requested. " +
  127. "RememberMe functionality will not be executed for corresponding account.");
  128. }
  129. }
  130. }
  131. public void rememberIdentity(AuthenticationToken submittedToken, AuthenticationInfo successfullyAuthenticated) {
  132. rememberIdentity(successfullyAuthenticated);
  133. }
  134. public void rememberIdentity(AuthenticationInfo successfullyAuthenticated) {
  135. PrincipalCollection principals = getIdentityToRemember(successfullyAuthenticated);
  136. rememberIdentity(principals);
  137. }
  138. protected PrincipalCollection getIdentityToRemember(AuthenticationInfo info) {
  139. return info.getPrincipals();
  140. }
  141. protected void rememberIdentity(PrincipalCollection accountPrincipals) {
  142. try {
  143. byte[] bytes = serialize(accountPrincipals);
  144. if (getCipher() != null) {
  145. bytes = encrypt(bytes);
  146. }
  147. rememberSerializedIdentity(bytes);
  148. } catch (SerializationException se) {
  149. if (log.isWarnEnabled()) {
  150. log.warn("Unable to serialize account principals [" + accountPrincipals + "]. Identity " +
  151. "cannot be remembered! This is a non fatal exception as RememberMe identity services " +
  152. "are not considered critical and execution can continue as normal. But please " +
  153. "investigate and resolve to prevent seeing this message again.", se);
  154. }
  155. }
  156. }
  157. public PrincipalCollection getRememberedPrincipals() {
  158. try {
  159. PrincipalCollection principals = null;
  160. byte[] bytes = getSerializedRememberedIdentity();
  161. if (bytes != null) {
  162. if (getCipher() != null) {
  163. bytes = decrypt(bytes);
  164. }
  165. try {
  166. principals = deserialize(bytes);
  167. } catch (SerializationException e) {
  168. if (log.isWarnEnabled()) {
  169. log.warn("Unable to deserialize stored identity byte array. Remembered identity " +
  170. "cannot be reconstituted! This is a non fatal exception as RememberMe identity services " +
  171. "are not considered critical and execution can continue as normal, but please " +
  172. "investigate and resolve to prevent seeing this message again.", e);
  173. }
  174. }
  175. }
  176. return principals;
  177. } catch (Exception e) {
  178. return onRememberedPrincipalFailure(e);
  179. }
  180. }
  181. /**
  182. * Called when an exception is thrown while trying to retrieve principals. The default implementation logs a
  183. * warning and forgets ('unremembers') the problem identity by calling {@link #forgetIdentity() forgetIdentity()}.
  184. * This most commonly would occur when an encryption key is updated and old principals are retrieved that have
  185. * been encrypted with the previous key.\
  186. *
  187. * @param e the exception that was thrown.
  188. * @return <code>null</code> in all cases.
  189. */
  190. protected PrincipalCollection onRememberedPrincipalFailure(Exception e) {
  191. if (log.isWarnEnabled()) {
  192. log.warn("There was a failure while trying to retrieve remembered principals. This could be due to a " +
  193. "configuration problem or corrupted principals. This could also be due to a recently " +
  194. "changed encryption key. The remembered identity will be forgotten and not used for this " +
  195. "request.", e);
  196. }
  197. forgetIdentity();
  198. return null;
  199. }
  200. protected byte[] encrypt(byte[] serialized) {
  201. byte[] value = serialized;
  202. Cipher cipher = getCipher();
  203. if (cipher != null) {
  204. value = cipher.encrypt(serialized, getEncryptionCipherKey());
  205. }
  206. return value;
  207. }
  208. protected byte[] decrypt(byte[] encrypted) {
  209. byte[] serialized = encrypted;
  210. Cipher cipher = getCipher();
  211. if (cipher != null) {
  212. serialized = cipher.decrypt(encrypted, getDecryptionCipherKey());
  213. }
  214. return serialized;
  215. }
  216. protected byte[] serialize(PrincipalCollection principals) {
  217. return getSerializer().serialize(principals);
  218. }
  219. protected PrincipalCollection deserialize(byte[] serializedIdentity) {
  220. return (PrincipalCollection) getSerializer().deserialize(serializedIdentity);
  221. }
  222. public void onFailedLogin(AuthenticationToken token, AuthenticationException ae) {
  223. forgetIdentity(token, ae);
  224. }
  225. public void onLogout(PrincipalCollection subjectPrincipals) {
  226. forgetIdentity();
  227. }
  228. protected void forgetIdentity(AuthenticationToken token, AuthenticationException ae) {
  229. forgetIdentity(token);
  230. }
  231. protected void forgetIdentity(AuthenticationToken token) {
  232. forgetIdentity();
  233. }
  234. }