URL加密解密完整解决方案.docx
- 文档编号:16775081
- 上传时间:2023-07-17
- 格式:DOCX
- 页数:13
- 大小:18.77KB
URL加密解密完整解决方案.docx
《URL加密解密完整解决方案.docx》由会员分享,可在线阅读,更多相关《URL加密解密完整解决方案.docx(13页珍藏版)》请在冰点文库上搜索。
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两个包。
下面是具体的实现:
importjavax.mail.internet.MimeUtility;
publicclassBase64{
publicstaticbyte[]encode(byte[]b)throwsException{
ByteArrayOutputStreambaos=null;
OutputStreamb64os=null;
try{
baos=newByteArrayOutputStream();
b64os=MimeUtility.encode(baos,"base64");
b64os.write(b);
b64os.close();
returnbaos.toByteArray();
}catch(Exceptione){
thrownewException(e);
}finally{
try{
if(baos!
=null){
baos.close();
baos=null;
}
}catch(Exceptione){
}
try{
if(b64os!
=null){
b64os.close();
b64os=null;
}
}catch(Exceptione){
}
}
}
publicstaticbyte[]decode(byte[]b)throwsException{
ByteArrayInputStreambais=null;
InputStreamb64is=null;
try{
bais=newByteArrayInputStream(b);
b64is=MimeUtility.decode(bais,"base64");
byte[]tmp=newbyte[b.length];
intn=b64is.read(tmp);
byte[]res=newbyte[n];
System.arraycopy(tmp,0,res,0,n);
returnres;
}catch(Exceptione){
thrownewException(e);
}finally{
try{
if(bais!
=null){
bais.close();
bais=null;
}
}catch(Exceptione){
}
try{
if(b64is!
=null){
b64is.close();
b64is=null;
}
}catch(Exceptione){
}
}
}
}
四、加密解密工具类的实现
有了BASE64的工具类,下面的工作将变得简单了,编写我们的加密解密工具类吧:
importjava.io.DataOutputStream;
importjava.io.FileOutputStream;
importjava.security.*;
importjavax.crypto.*;
importjavax.crypto.spec.*;
importjava.util.*;
importmons.logging.Log;
importmons.logging.LogFactory;
publicclassSecurityHelper{
protectedfinalstaticLoglogger=LogFactory.getLog(SecurityHelper.class);
privatefinalstaticintITERATIONS=20;
publicstaticStringencrypt(Stringkey,StringplainText)throwsException{
StringencryptTxt="";
try{
byte[]salt=newbyte[8];
MessageDigestmd=MessageDigest.getInstance("MD5");
md.update(key.getBytes());
byte[]digest=md.digest();
for(inti=0;i<8;i++){
salt[i]=digest[i];
}
PBEKeySpecpbeKeySpec=newPBEKeySpec(key.toCharArray());
SecretKeyFactorykeyFactory=SecretKeyFactory
.getInstance("PBEWithMD5AndDES");
SecretKeyskey=keyFactory.generateSecret(pbeKeySpec);
PBEParameterSpecparamSpec=newPBEParameterSpec(salt,ITERATIONS);
Ciphercipher=Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.ENCRYPT_MODE,skey,paramSpec);
byte[]cipherText=cipher.doFinal(plainText.getBytes());
StringsaltString=newString(Base64.encode(salt));
StringciphertextString=newString(Base64.encode(cipherText));
returnsaltString+ciphertextString;
}catch(Exceptione){
thrownewException("EncryptTextError:
"+e.getMessage(),e);
}
}
publicstaticStringdecrypt(Stringkey,StringencryptTxt)
throwsException{
intsaltLength=12;
try{
Stringsalt=encryptTxt.substring(0,saltLength);
Stringciphertext=encryptTxt.substring(saltLength,encryptTxt
.length());
byte[]saltarray=Base64.decode(salt.getBytes());
byte[]ciphertextArray=Base64.decode(ciphertext.getBytes());
PBEKeySpeckeySpec=newPBEKeySpec(key.toCharArray());
SecretKeyFactorykeyFactory=SecretKeyFactory
.getInstance("PBEWithMD5AndDES");
SecretKeyskey=keyFactory.generateSecret(keySpec);
PBEParameterSpecparamSpec=newPBEParameterSpec(saltarray,
ITERATIONS);
Ciphercipher=Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.DECRYPT_MODE,skey,paramSpec);
byte[]plaintextArray=cipher.doFinal(ciphertextArray);
returnnewString(plaintextArray);
}catch(Exceptione){
thrownewException(e);
}
}
注意上面加粗的三处地方:
privatefinalstaticintITERATIONS=20;
上面的值越大,加密越深,一般例子都以"Java安全性编程指南”这本书中的例子的值为准,设成1000,我们在这边只需要20就够了,原因就是考虑到加解密的速度问题。
intsaltLength=12;
这是base64解码后的盐的长度,加密后再经BASE64编码后盐的长度为8,BASE64解码后盐的长度为12,至于为什么,这也是根据BASE64的原理得出的,具体可以看BASE64原理,网上很多,说得也都很简单。
PBEWithMD5AndDES
我们使用的是PBEWithMD5AndDES加密。
下面编写一个测试类
publicstaticvoidmain(String[]args){
StringencryptTxt="";
StringplainTxt="helloohmygod";
try{
System.out.println(plainTxt);
encryptTxt=encrypt("mypassword01",plainTxt);
plainTxt=decrypt("mypassword01",encryptTxt);
System.out.println(encryptTxt);
System.out.println(plainTxt);
}catch(Exceptione){
e.printStackTrace();
System.exit(-1);
}
}
}
五、工具类在strutsaction中的具体使用
MyTaskDTOtaskDTO=newMyTaskDTO();
TaskInstanceti=(TaskInstance)it.next();
taskDTO.setTaskName(ti.getName());
taskDTO.setTaskCreateDate(sd.format(ti.getCreate()));
taskDTO.setTaskDescr(ti.getDescription());
/*noencrypteddata*/
StringtaskId=String.valueOf(ti.getId());
StringtokenId=String.valueOf(ti.getToken().getId());
processImgName=PropertyUtil.getProperty(
Constants.BPM_PROCESS_PAYMENT_PROCESSIMAGE).toString()
+".jpg";
processDefId=String.valueOf(ti.getToken()
.getProcessInstance().getProcessDefinition().getId());
/*encrypteddata*/
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页面的处理如下:
StringprocessImgPath=taskDTO.getProcessImageName();
StringprocessDefId=taskDTO.getProcessDefinitionId();
processImgPath=.URLEncoder.encode(processImgPath,"UTF-8");
processDefId=.URLEncoder.encode(processDefId,"UTF-8");
StringshowProcessImgUrl=request.getContextPath()+"/queryMyTask.do";
method=showProcessImg&processDefinitionId=<%=processDefId%>&processImgPath=<%=processImgPath%>"target="_blank">
七、在接受加密参数的action中对加密的值进行解密
我们假设我们的接受的action为:
queryMyTask.do,它接受一系列的参数,基中,processDefId和processImgPath是加密的。
实现如下:
StringprocessImgFilePath="";
StringprocessDefinitionId=(String)request.getParameter("processDefinitionId");
processImgFilePath=(String)request.getParameter("processImgPath");
processDefinitionId=EncryptUrlPara.decrypt(processDefinitionId);
processImgFilePath=EncryptUrlPara.decrypt(processImgFilePath);
需要注意的是此处不需要再decode了。
八、key(口令)的存放
因为我们这边的key就是口令,是一个文本,我们将它存放在server端的properties中,当然,我们也是加密存放的。
我们使用spring+jasypt1.5(javasimpleencrypt包)。
设我们有一个properties文件,其中:
security.des.key=ENC(OlO0LqELUuLOVreCtDngHaNgMcZWUyUg)
这个就是我们在encrypt和decrypt方法中用到的key.
我们不希望这个key以明文的形式设在properties中,我们对这个key再进行一次加密用的同样也是PBEWithMD5AndDES,当然因为有了spring因为有了jasypt包,因此这个过程一切是自动的。
我们使用jasypt包下的bin中自带的encrypt.bat工具:
encryptinput=mykey password=secret algorithm=PBEWithMD5AndDES
该命令会输出一行乱码,把这行乱码复制到properties文件中,在外层加上ENC(),如:
生成:
OlO0LqELUuLOVreCtDngHaNgMcZWUyUg
放入properties后需要转换成:
ENC(OlO0LqELUuLOVreCtDngHaNgMcZWUyUg)
然后在工程布署的机器上需要设一个环境变理,如:
setAPP_ENCRYPTION_PASSWORD=secret 此处的值必须和上面encrypt.bat命令行中的password=后的值一样。
(linux请用exportAPP_ENCRYPTION_PASSWORD=secret)
然后配置spring,使该properties在工程被app容器load时,自动解密,这样我们在我们的方法中直接取到该KEY时就已经是明文了(解密过程是jasypt+spring自动完成的),以下是这一步配置的详细内容:
component-scanbase-package="jbpmweb"/> class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig" p: algorithm="PBEWithMD5AndDES"p: passwordEnvName="APP_ENCRYPTION_PASSWORD"/> -- Thewillbetheencryptorusedfordecryptingconfigurationvalues. --> p: config-ref="environmentVariablesConfiguration"/> class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer"> xxx.properties -- Configurerthatreplaces${...}placeholderswithvaluesfroma propertiesfile --> property-placeholderlocation="classpath: jbpmweb.properties"/> p: systemPropertiesModeName="SYSTEM_PROPERTIES_MODE_OVERRIDE"p: encryptor-ref="configurationEncryptor"> factory-method="getConfiguration"/>
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- URL 加密 解密 完整 解决方案