All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.util.StateUtils Maven / Gradle / Ivy

Go to download

The MyFaces Commons Subproject provides base classes for usage in both the MyFaces implementation and the MyFaces Tomahawk components. This is also a general set of utility classes for usage in your JSF projects independent of the implementation you might be deciding upon.

The newest version!
/*
 * Copyright 2004-2006 The Apache Software Foundation.
 *
 * 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.
 */
package org.apache.myfaces.util;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * 

This Class exposes a handful of methods related to encryption, * compression and serialization.

* *
    *
  • ISO-8859-1 is the character set used.
  • *
  • GZIP is used for all compression/decompression.
  • *
  • Base64 is used for all encoding and decoding.
  • *
* *

To enable encryption, a secret must be provided. StateUtils looks first * for the org.apache.myfaces.secret init param, then system properties. * If a secret cannot be located, encryption is not used.

* *
    *
  • DES is the default encryption algorithm
  • *
  • ECB is the default mode
  • *
  • PKCS5Padding is the default padding
  • *
  • The default algorithm can be overridden using the * org.apache.myfaces.algorithm parameter
  • *
  • The default mode and padding can be overridden using the * org.apache.myfaces.algorithm.parameters parameter
  • *
  • The defaults are not recommended
  • *
  • This utility has not been tested with modes other than ECB and CBC
  • *
  • An initialization vector can be specified via the * org.apache.myfaces.algorithm.parameters parameter
  • *
* *

All parameters are interpretted as base 64 encoded keys. In other * words, if your secret is "76543210", you would put "NzY1NDMyMTA=" in * the deployment descriptor. This is needed so that key values are not * limited to just values composed of printable characters.

* *

If you are using CBC mode encryption, you must specify an * initialization vector. StateUtils will throw an exception otherwise.

* *

If you are using the AES algorithm and getting a SecurityException * complaining about keysize, you most likely need to get the unlimited * strength jurisdiction policy files from a place like * http://java.sun.com/j2se/1.4.2/download.html .

* * @author Dennis C. Byrne, ich */ public class StateUtils { private static final Log log = LogFactory.getLog(StateUtils.class); public static final String ZIP_CHARSET = "ISO-8859-1"; // encryption related properties private static byte[] secret; private static String algorithm = "DES"; private static String algorithmParams = "ECB/PKCS5Padding"; private static byte[] iv; // initialization vector for CBC mode public static final String INIT_PREFIX = "org.apache.myfaces."; public static final String INIT_SECRET = INIT_PREFIX + "secret"; public static final String INIT_ALGORITHM = INIT_PREFIX + "algorithm"; public static final String INIT_ALGORITHM_IV = INIT_PREFIX + "algorithm.iv"; public static final String INIT_ALGORITHM_PARAM = INIT_PREFIX + "algorithm.parameters"; private static boolean secure = false; static { FacesContext ctx = FacesContext.getCurrentInstance(); String _secret; String _algorithm; String _algorithmParams; String _iv; // initialization vector if (ctx != null) { _secret = ctx.getExternalContext().getInitParameter(INIT_SECRET); _algorithm = ctx.getExternalContext().getInitParameter(INIT_ALGORITHM); _algorithmParams = ctx.getExternalContext().getInitParameter(INIT_ALGORITHM_PARAM); _iv = ctx.getExternalContext().getInitParameter(INIT_ALGORITHM_IV); } else { // TODO remove this // not recommended for users ... mostly here for testing _secret = System.getProperty(INIT_SECRET); _algorithm = System.getProperty(INIT_ALGORITHM); _algorithmParams = System.getProperty(INIT_ALGORITHM_PARAM); _iv = System.getProperty(INIT_ALGORITHM_IV); } if (_secret == null) { log.debug("secret for " + INIT_SECRET + " not located, encryption disabled"); } else { if (_algorithmParams != null && _algorithmParams.startsWith("CBC") & _iv == null ) { throw new FacesException(INIT_ALGORITHM_PARAM + " parameter has been set with CBC mode," + " but no initialization vector has been set " + " with " + INIT_ALGORITHM_IV); } secret = new Base64().decode(_secret.getBytes()); if (_algorithm != null) algorithm = _algorithm; if (_algorithmParams != null) algorithmParams = _algorithmParams; if (_iv != null) iv = new Base64().decode(_iv.getBytes()); secure = true; log.debug("encryption enabled using " + algorithm + "/" + algorithmParams); } } public static boolean isSecure() { return secure; } /** * This fires during the Render Response phase. */ public static final String construct(Object object){ byte[] bytes = getAsByteArray(object); if(secure) bytes = encrypt(bytes); bytes = compress(bytes); bytes = encode(bytes); try { return new String(bytes, ZIP_CHARSET); } catch (UnsupportedEncodingException e) { throw new FacesException(e); } } public static final byte[] getAsByteArray(Object object) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { ObjectOutputStream writer = new ObjectOutputStream(outputStream); writer.writeObject(object); byte[] bytes = outputStream.toByteArray(); writer.close(); outputStream.close(); writer = null; outputStream = null; return bytes; } catch (IOException e) { throw new FacesException(e); } } public static byte[] encrypt(byte[] insecure) { try { // note: keep it local to avoid threading issues SecretKey secretKey = new SecretKeySpec(secret, algorithm); Cipher cipher = Cipher.getInstance(algorithm + "/" + algorithmParams); if(iv != null){ IvParameterSpec ivSpec = new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); }else{ cipher.init(Cipher.ENCRYPT_MODE, secretKey); } return cipher.doFinal(insecure); } catch (Exception e) { throw new FacesException(e); } } public static final byte[] compress(byte[] bytes) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { GZIPOutputStream gzip = new GZIPOutputStream(baos); gzip.write(bytes, 0, bytes.length); gzip.finish(); byte[] fewerBytes = baos.toByteArray(); gzip.close(); baos.close(); gzip = null; baos = null; return fewerBytes; } catch (IOException e) { throw new FacesException(e); } } public static final byte[] encode(byte[] bytes) { return new Base64().encode(bytes); } /** * This fires during the Restore View phase. */ public static final Object reconstruct(String string){ byte[] bytes; try { bytes = string.getBytes(ZIP_CHARSET); bytes = decode(bytes); bytes = decompress(bytes); if(secure) bytes = decrypt(bytes); return getAsObject(bytes); } catch (UnsupportedEncodingException e) { throw new FacesException(e); } } public static final byte[] decode(byte[] bytes) { return new Base64().decode(bytes); } public static final byte[] decompress(byte[] bytes) { ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[2048]; int length; try { GZIPInputStream gis = new GZIPInputStream(bais); while ((length = gis.read(buffer)) != -1) { baos.write(buffer, 0, length); } byte[] moreBytes = baos.toByteArray(); baos.close(); bais.close(); gis.close(); baos = null; bais = null; gis = null; return moreBytes; } catch (IOException e) { throw new FacesException(e); } } public static byte[] decrypt(byte[] secure) { try { // note: keep it local to avoid threading issues SecretKey secretKey = new SecretKeySpec(secret, algorithm); Cipher cipher = Cipher.getInstance(algorithm + "/" + algorithmParams); if(iv != null) { IvParameterSpec ivSpec = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec); } else { cipher.init(Cipher.DECRYPT_MODE, secretKey); } return cipher.doFinal(secure); } catch (Exception e) { throw new FacesException(e); } } public static final Object getAsObject(byte[] bytes) { ByteArrayInputStream input = new ByteArrayInputStream(bytes); try { ObjectInputStream s = new ObjectInputStream(input); Object object = s.readObject(); s.close(); input.close(); s = null; input = null; return object; } catch (Exception e) { throw new FacesException(e); } } public static String encode64(Object obj) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream zos = new GZIPOutputStream(baos); ObjectOutputStream oos = new ObjectOutputStream(zos); oos.writeObject(obj); oos.close(); zos.close(); baos.close(); Base64 base64Codec = new Base64(); return new String(base64Codec.encode( baos.toByteArray() ), ZIP_CHARSET); } catch (IOException e) { log.fatal("Cannot encode Object with Base64", e); throw new FacesException(e); } } public static byte[] getSecret() { return secret; } public static void setSecret(String _secret) { secret = new Base64().decode(_secret.getBytes()); } public static void setSecret(byte[] secret) { StateUtils.secret = secret; } public static String getAlgorithm() { return algorithm; } public static void setAlgorithm(String algorithm) { StateUtils.algorithm = algorithm; } public static String getAlgorithmParams() { return algorithmParams; } public static void setAlgorithmParams(String algorithmParams) { StateUtils.algorithmParams = algorithmParams; } public static byte[] getIv() { return iv; } public static void setIv(String _iv) { iv = new Base64().decode(_iv.getBytes()); } public static void setIv(byte[] iv) { StateUtils.iv = iv; } public static void main (String[] args) throws UnsupportedEncodingException { byte[] bytes = encode(args[0].getBytes(ZIP_CHARSET)); System.out.println(new String(bytes, ZIP_CHARSET)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy