Reputation:
I am looking for url security. It just like when i use Struts2 url tag in Struts2 anchor tag then the url's parameters needs to be encrypted, so that nobody can tampered the data. when request reached to my filter the the parameter need to be encrypted and the corresponding action will call after that. For this i research and done some coding:
UrlEncryptedParameterTag:
public class UrlEncryptedParameterTag extends UrlTag
{
/**
* Encrypts and adds a parameter under the name/key contained
* within the encryptedParameterName property.
*
* @param name The parameter name.
* @param value The parameter value.
*/
public void addParameter(String name, String value)
{
value = ParameterEncryptor.encrypt(name, value);
super.addParameter(name, value);
}
}
ParameterEncryptor:
public class ParameterEncryptor {
private static final String ALGO = "AES";
private static Logger log = Logger.getLogger(UrlEncryptedParameterTag.class);
private static byte[] keyValue = new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't','S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };
public static String encrypt(String name, String value)
{
log.debug("Encrypting request parameter: " + name);
Key key = generateKey();
Cipher c =null;
try {
c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(value.getBytes());
value = new BASE64Encoder().encode(encVal);
} catch (NoSuchAlgorithmException ex) {
log.error(ex.getMessage());
} catch (NoSuchPaddingException ex) {
log.error(ex.getMessage());
} catch (InvalidKeyException ex) {
log.error(ex.getMessage());
} catch (IllegalBlockSizeException ex) {
log.error(ex.getMessage());
} catch (BadPaddingException ex) {
log.error(ex.getMessage());
}
return value;
}
public static String decrypt(String encryptedData) {
String decryptedValue = "";
try{
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
decryptedValue = new String(decValue);
} catch (NoSuchAlgorithmException ex) {
log.error(ex.getMessage());
} catch (NoSuchPaddingException ex) {
log.error(ex.getMessage());
} catch (InvalidKeyException ex) {
log.error(ex.getMessage());
} catch (IllegalBlockSizeException ex) {
log.error(ex.getMessage());
} catch (BadPaddingException ex) {
log.error(ex.getMessage());
} catch (IOException ex) {
log.error(ex.getMessage());
}
return decryptedValue;
}
private static Key generateKey() {
Key key = new SecretKeySpec(keyValue, ALGO);
return key;
}
}
Filter class:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
Enumeration<String> paramNames = request.getParameterNames();
while(paramNames.hasMoreElements()){
String paramName = paramNames.nextElement();
String encryptedParamtersStrings[] = request.getParameterValues(paramName);
for (String encryptedParametersString : encryptedParamtersStrings) {
if (StringUtils.isNotBlank(encryptedParametersString)) {
String decryptedParametersString = ParameterEncryptor.decrypt(encryptedParametersString);
// Map<String, String> parameterMap = MapSupport.delimitedNameValuesStringToMap(decryptedParametersString, "&", "=");
//for (String attributeName : parameterMap.keySet()) {
request.setAttribute(paramName, decryptedParametersString);
//}
}
}
// Remove the encrypted name-value pairs from the request
//request.removeAttribute(paramNames.nextElement());
}
// Continue processing of the chain
chain.doFilter(request, response);
}
Now, here i have stuck how to go further.
Upvotes: 0
Views: 617
Reputation: 2319
You cannot change the request parameters of that request directly - which I suppose is the point where you got stuck.
Instead you might want trying to wrap the request before passing it to the chain.doFilter(...)
and the wrapper object will then do all the decoding on the fly:
HttpServletRequest request = (HttpServletRequest) req;
DecodingParameterHttpServletRequest decodingRequest = new DecodingParameterHttpServletRequest(request);
chain.doFilter(decodingRequest, resp);
The DecodingParameterHttpServletRequest
extends HttpServletRequestWrapper
and only overwrites the methods which return HTTP request parameters. The methods first fetch the undecoded values, then decode them and return the decoded data.
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class DecodingParameterHttpServletRequest extends HttpServletRequestWrapper {
public DecodingParameterHttpServletRequest(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String undecodedValue = super.getParameter(name);
if (undecodedValue == null) {
return null;
}
return ParameterEncryptor.decrypt(undecodedValue);
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String,String[]> map = super.getParameterMap();
if ((map == null) || (map.isEmpty() == true)) {
return map;
}
Map<String,String[]> decodedMap = new LinkedHashMap<String, String[]>();
List<String> entryNames = new LinkedList<String>(map.keySet());
for (String entryName : entryNames) {
String[] entryValues = map.get(entryName);
if (entryValues != null) {
for (int i = 0; i < entryValues.length; i++) {
if (entryValues[i] != null) {
entryValues[i] = ParameterEncryptor.decrypt(entryValues[i]);
}
}
}
decodedMap.put(entryName, entryValues);
}
return decodedMap;
}
@Override
public String[] getParameterValues(String name) {
String[] undecodedValues = super.getParameterValues(name);
if ((undecodedValues == null) || (undecodedValues.length == 0)) {
return undecodedValues;
}
String[] decodedValues = new String[undecodedValues.length];
for (int i = 0; i < undecodedValues.length; i++) {
decodedValues[i] = ParameterEncryptor.decrypt(undecodedValues[i]);
}
return decodedValues;
}
}
Upvotes: 1