当前位置:文档之家› URL加密解密完整解决方案

URL加密解密完整解决方案

URL加密解密完整解决方案采用:.URLEncoder.encode(Base64编码(加密字串), StringCode) 这样的方法来对url中的参数进行加密。

首先我们先说一下如何加密。

一、算法的选择:对于像对url中的参数进行加密的过程,我不建议使用rsa或者是三重des这样的加密算法,主要原因在于性能和速度会受影响。

我建议大家使用对称加密如:DES或者是PBE算法。

我们在这边就使用PBEWithMD5AndDES来实现加密。

二、加密原理对于一个纯文本,加密后它会变成一堆乱码,这堆乱码包括了许多非法字符,我们不希望把这些字符放入bean中,因此在加密完后,我们还要对加密结果进行base64编码。

PBE从字面上理解,它必须使用一个口令,我们不希望我们的加密过于复杂而影响页面跳转的速度,因此我们不采用口令+KEY的形式,我们这边的口令就是我们的KEY。

因此:我们的整个加密过程实现如下:输入口令(KEY)--> 加密文本 --> 以base64对加密后的结果进行编码-->以.URLEncoder.encode编码成浏览器可以识别的形式-->传输给接受的action而解密过程如下:接受的action得到参数-->以base64对结果进行解码-->得到纯加密文本-->解密-->得到解密后的值三、BASE64这边对于BASE64的原理不多说了,只说实现,目前网上有很多实现方式,有自己写的,有用sun.misc.*的,我们在这个例子里将使用javax.mail.internet.MimeUtility自带的base64编码工具。

需要引入activation.jar和mail.jar两个包。

下面是具体的实现:import javax.mail.internet.MimeUtility;public class Base64 {public static byte[] encode(byte[] b) throws Exception {ByteArrayOutputStream baos = null;OutputStream b64os = null;try {baos = new ByteArrayOutputStream();b64os = MimeUtility.encode(baos, "base64");b64os.write(b);b64os.close();return baos.toByteArray();} catch (Exception e) {throw new Exception(e);} finally {try {if (baos != null) {baos.close();baos = null;}} catch (Exception e) {}try {if (b64os != null) {b64os.close();b64os = null;}} catch (Exception e) {}}}public static byte[] decode(byte[] b) throws Exception { ByteArrayInputStream bais = null;InputStream b64is = null;try {bais = new ByteArrayInputStream(b);b64is = MimeUtility.decode(bais, "base64");byte[] tmp = new byte[b.length];int n = b64is.read(tmp);byte[] res = new byte[n];System.arraycopy(tmp, 0, res, 0, n);return res;} catch (Exception e) {throw new Exception(e);} finally {try {if (bais != null) {bais.close();bais = null;}} catch (Exception e) {}try {if (b64is != null) {b64is.close();b64is = null;}} catch (Exception e) {}}}}四、加密解密工具类的实现有了BASE64的工具类,下面的工作将变得简单了,编写我们的加密解密工具类吧:import java.io.DataOutputStream;import java.io.FileOutputStream;import java.security.*;import javax.crypto.*;import javax.crypto.spec.*;import java.util.*;import mons.logging.Log;import mons.logging.LogFactory;public class SecurityHelper {protected final static Log logger = LogFactory.getLog(SecurityHelper.class);private final static int ITERATIONS = 20;public static String encrypt(String key, String plainText) throws Exception {String encryptTxt = "";try {byte[] salt = new byte[8];MessageDigest md = MessageDigest.getInstance("MD5");md.update(key.getBytes());byte[] digest = md.digest();for (int i = 0; i < 8; i++) {salt[i] = digest[i];}PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");SecretKey skey = keyFactory.generateSecret(pbeKeySpec);PBEParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS); Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");cipher.init(Cipher.ENCRYPT_MODE, skey, paramSpec);byte[] cipherText = cipher.doFinal(plainText.getBytes());String saltString = new String(Base64.encode(salt));String ciphertextString = new String(Base64.encode(cipherText));return saltString + ciphertextString;} catch (Exception e) {throw new Exception("Encrypt Text Error:" + e.getMessage(), e);}}public static String decrypt(String key, String encryptTxt)throws Exception {int saltLength = 12;try {String salt = encryptTxt.substring(0, saltLength);String ciphertext = encryptTxt.substring(saltLength, encryptTxt.length());byte[] saltarray = Base64.decode(salt.getBytes());byte[] ciphertextArray = Base64.decode(ciphertext.getBytes());PBEKeySpec keySpec = new PBEKeySpec(key.toCharArray());SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");SecretKey skey = keyFactory.generateSecret(keySpec);PBEParameterSpec paramSpec = new PBEParameterSpec(saltarray,ITERATIONS);Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");cipher.init(Cipher.DECRYPT_MODE, skey, paramSpec);byte[] plaintextArray = cipher.doFinal(ciphertextArray);return new String(plaintextArray);} catch (Exception e) {throw new Exception(e);}}注意上面加粗的三处地方:private final static int ITERATIONS = 20;上面的值越大,加密越深,一般例子都以"Java安全性编程指南”这本书中的例子的值为准,设成1000,我们在这边只需要20就够了,原因就是考虑到加解密的速度问题。

int saltLength = 12;这是base64解码后的盐的长度,加密后再经BASE64编码后盐的长度为8,BASE64解码后盐的长度为12,至于为什么,这也是根据BASE64的原理得出的,具体可以看BASE64原理,网上很多,说得也都很简单。

PBEWithMD5AndDES我们使用的是PBEWithMD5AndDES加密。

下面编写一个测试类public static void main(String[] args) {String encryptTxt = "";String plainTxt = "hello oh my god";try {System.out.println(plainTxt);encryptTxt = encrypt("mypassword01", plainTxt);plainTxt = decrypt("mypassword01", encryptTxt);System.out.println(encryptTxt);System.out.println(plainTxt);} catch (Exception e) {e.printStackTrace();System.exit(-1);}}}五、工具类在struts action中的具体使用MyTaskDTO taskDTO = new MyTaskDTO();TaskInstance ti = (TaskInstance) it.next();taskDTO.setTaskName(ti.getName());taskDTO.setTaskCreateDate(sd.format(ti.getCreate()));taskDTO.setTaskDescr(ti.getDescription());/* no encrypted data */String taskId = String.valueOf(ti.getId());String tokenId = String.valueOf(ti.getToken().getId());processImgName = PropertyUtil.getProperty(Constants.BPM_PROCESS_PAYMENT_PROCESSIMAGE).toString()+ ".jpg";processDefId = String.valueOf(ti.getToken().getProcessInstance().getProcessDefinition().getId());/* encrypted data */taskId = EncryptUrlPara.encrypt(taskId);tokenId = EncryptUrlPara.encrypt(tokenId);processImgName = EncryptUrlPara.encrypt(processImgName);processDefId = EncryptUrlPara.encrypt(processDefId);taskDTO.setTaskId(taskId);taskDTO.setTokenId(tokenId);taskDTO.setProcessDefinitionId(processDefId);taskDTO.setProcessImageName(processImgName);六、jsp页面中的encode把上述这个bean放入request中,带到下一个jsp页面中后,在jsp页面的处理如下:String processImgPath=taskDTO.getProcessImageName();String processDefId=taskDTO.getProcessDefinitionId();processImgPath=.URLEncoder.encode(processImgPath,"UTF-8");processDefId=.URLEncoder.encode(processDefId,"UTF-8");String showProcessImgUrl=request.getContextPath()+"/queryMyTask.do";<ahref="<%=showProcessImgUrl%>?method=showProcessImg&processDefinitionId=<%=processD efId%>&processImgPath=<%=processImgPath%>" target="_blank"><u><span class="left_txt">查看当前进程</span></u></a>七、在接受加密参数的action中对加密的值进行解密我们假设我们的接受的action为: queryMyTask.do,它接受一系列的参数,基中,processDefId和processImgPath是加密的。

相关主题