java url 加密解密 解決方案 )

來源:互聯網
上載者:User

採用:

 

java.net.URLEncoder.encode(Base64編碼(加密字串), StringCode) 這樣的方法來對url中的參數進行加密。

 

首先我們先說一下如何加密。

 

一、演算法的選擇:

 

對於像對url中的參數進行加密的過程,我不建議使用rsa或者是三重des這樣的密碼編譯演算法,主要原因在於效能和速度會受影響。

 

我建議大家使用對稱式加密如:DES或者是PBE演算法。

 

我們在這邊就使用PBEWithMD5AndDES來實現加密。

 

二、加密原理

 

對於一個純文字,加密後它會變成一堆亂碼,這堆亂碼包括了許多非法字元,我們不希望把這些字元放入bean中,因此在加密完後,我們還要對加密結果進行base64編碼。

 

PBE從字面上理解,它必須使用一個口令,我們不希望我們的加密過於複雜而影響頁面跳轉的速度,因此我們不採用口令+KEY的形式,我們這邊的口令就是我們的KEY。

 

因此:

 

我們的整個加密過程實現如下:

 

輸入口令(KEY)--> 加密文本 --> 以base64對加密後的結果進行編碼-->以java.net.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 org.apache.commons.logging.Log;
import org.apache.commons.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=java.net.URLEncoder.encode(processImgPath,"UTF-8");
    processDefId=java.net.URLEncoder.encode(processDefId,"UTF-8");
    String showProcessImgUrl=request.getContextPath()+"/queryMyTask.do";

  <a href="<%=showProcessImgUrl%>?method=showProcessImg&processDefinitionId=<%=processDefId%>&processImgPath=<%=processImgPath%>" target="_blank"><u><span class="left_txt">查看當前進程</span></u></a>

七、在接受加密參數的action中對加密的值進行解密

我們假設我們的接受的action為: queryMyTask.do,它接受一系列的參數,基中,processDefId和processImgPath是加密的。

實現如下:

String processImgFilePath = "";
 String processDefinitionId = (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(java simple encrypt包)。

 

設我們有一個properties檔案,其中:

security.des.key=ENC(OlO0LqELUuLOVreCtDngHaNgMcZWUyUg)

這個就是我們在encrypt和decrypt方法中用到的key.

我們不希望這個key以明文的形式設在properties中,我們對這個key再進行一次加密用的同樣也是PBEWithMD5AndDES,當然因為有了spring因為有了jasypt包,因此這個過程一切是自動的。

我們使用jasypt包下的bin中內建的encrypt.bat工具:

 

encrypt input=mykey password=secret algorithm=PBEWithMD5AndDES

該命令會輸出一行亂碼,把這行亂碼複製到properties檔案中,在外層加上ENC(),如:

 

產生: OlO0LqELUuLOVreCtDngHaNgMcZWUyUg

放入properties後需要轉換成: ENC(OlO0LqELUuLOVreCtDngHaNgMcZWUyUg)

然後在工程布署的機器上需要設一個環境變理,如:

set APP_ENCRYPTION_PASSWORD=secret   此處的值必須和上面encrypt.bat命令列中的password=後的值一樣。

(linux請用export APP_ENCRYPTION_PASSWORD=secret)

 

然後配置spring,使該properties在工程被app 容器load時,自動解密,這樣我們在我們的方法中直接取到該KEY時就已經是明文了(解密過程是jasypt+spring自動完成的),以下是這一步配置的詳細內容:

 

 <context:component-scan base-package="jbpmweb" />
 <bean id="environmentVariablesConfiguration"
  class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig"
  p:algorithm="PBEWithMD5AndDES" p:passwordEnvName="APP_ENCRYPTION_PASSWORD" />

 <!--
  The will be the encryptor used for decrypting configuration values.
 -->

 <bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor"
  p:config-ref="environmentVariablesConfiguration" />

 <bean id="propertyConfigurer"
  class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer">
  <constructor-arg ref="configurationEncryptor" />
  <property name="locations">
   <list>
    <value>classpath:xxx.properties</value>
   </list>
  </property>
 </bean>

 <!--
  Configurer that replaces ${...} placeholders with values from a
  properties file
 -->
 <context:property-placeholder location="classpath:jbpmweb.properties" />

 <bean id="commonsConfigurationFactoryBean" class="xxx.xxx.CommonsConfigurationFactoryBean"
  p:systemPropertiesModeName="SYSTEM_PROPERTIES_MODE_OVERRIDE" p:encryptor-ref="configurationEncryptor">
  <constructor-arg>
   <bean class="org.apache.commons.configuration.PropertiesConfiguration">
    <constructor-arg value="xxx.properties" />
   </bean>
  </constructor-arg>
 </bean>
 
  
 <bean id="propertiesConfiguration" factory-bean="&amp;commonsConfigurationFactoryBean"
  factory-method="getConfiguration"/>

轉載地址:http://blog.csdn.net/lifetragedy/article/details/6318017

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.