一般我们在form提交时不要担心我们的参数会显示给用户看。
我们主要解决的是以get方式进行url参数传递的问题,如:
http://xxx.xxx.xxx.xxx/xxx/xxx.do?pId=101&imageName=processimage.jpg这样的url pId=101&imageName=processimage.jgp这样的参数如何进行加密。
我们采用:
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="&commonsConfigurationFactoryBean" factory-method="getConfiguration"/>
相关推荐
在本文中,我们将深入探讨JSP页面传参出现中文乱码的原因,并提供有效的解决方案。 1. 乱码原因: - **编码与解码不匹配**:当JSP页面、Servlet或服务器配置的字符编码不一致时,中文字符在传输过程中可能被错误地...
在Web开发中,尤其是使用Java JSP技术时,我们可能会遇到URL中传递参数出现乱码的问题。这是因为不同的字符集编码方式可能导致字符在传输过程中无法正确解析。本文将详细介绍两种解决JSP页面URL参数乱码的方法,虽然...
在开发Java Web应用程序时,尤其是使用Struts2框架与JSP进行交互时,可能会遇到URL传参中文乱码的问题。这个问题通常涉及到字符编码的设置,包括客户端请求编码、服务器接收编码以及应用程序内部处理编码的统一。...
jsp使用URL编码传递中文参数乱码问题
jsp 传参 servlet 接收中文乱码问题的解决方法 jsp 传参 servlet 接收中文乱码问题是一个经常遇到的问题,特别是在使用 Hibernate+Servlet 框架时。当我们在 jsp 页面传参到 servlet 时,中文字符经常会出现乱码...
总之,`request`对象在J2EE开发中扮演着核心角色,处理中文乱码和URL传参是日常工作中常遇到的问题。了解和掌握这些知识点,将使你在Web开发中更加得心应手。通过不断的实践和学习,你将能够更好地应对各种复杂情况...
### JSP URL传参特殊字符处理 在JSP(JavaServer Pages)开发中,通过URL进行参数传递是一种常见的做法。然而,在实际应用中经常会遇到一些特殊字符如“#”、“&”等,这些字符如果不经过适当的编码处理,在传递...
在jsp网页中实现MD5加密可以使用JavaBean来实现。MD5类实现了RSA Data Security公司的MD5 message-digest算法。该类中定义了一些静态final变量,用于存储MD5算法中的矩阵值。这些矩阵值用于计算MD5哈希值。 MD5类还...
在本主题“base64 jsp版本加密及调用”中,我们将深入探讨如何在Java Server Pages (JSP)环境中使用Base64进行数据加密和解密,以及如何在实际应用中调用这些功能。 首先,Base64的原理是将每3个字节的数据(24位)...
- 传递敏感数据时要格外小心,可能需要加密或使用安全的传输层协议(如HTTPS)。 5. **示例**: 假设我们有一个JSP页面,它获取了用户ID和用户名: ```jsp <jsp:useBean id="userManager" class=...
"jsp加密解密问题.rar"这个压缩包文件很可能包含了关于如何在JSP中实现URL参数加密与解密的源代码示例。 URL参数加密的主要目的是防止敏感信息在传输过程中被窃取或篡改。这包括用户名、密码、交易详情等关键数据。...
JSP struts2 url传参中文乱码解决办法 1.设置struts.xml 或是设置struts.properties(我自己没试过) struts.i18n.encoding=UTF-8 2.在web.xml添加编码过滤器 <filter>characterEncodingFilter <filter>org....
前言 JSP 页面间传递参数是项目中经常需要的,这应该算是 web 基本功吧。试着将各种方式总结下来,需要时可以进行权衡利弊...<jsp page=next.jsp><jsp name=paramA value=A/></jsp> <jsp page=next.jsp><jsp:para
**JSP的SHA加密详解** 在Java Web开发中,数据安全性是至关重要的,尤其是在处理用户登录、密码存储等敏感信息时。SHA(Secure Hash Algorithm,安全散列算法)就是一种常用于增强数据安全性的加密技术。它将任意...
Head First Servlet JSP 中文无加密 可以编辑,打印等最高权限 工 6 部分
在JSP(JavaServer Pages)中,我们也可以实现MD5加密。 在JSP中使用MD5加密通常涉及以下步骤: 1. **引入必要的库**:JSP默认并没有内置MD5加密功能,因此我们需要引入`java.security.MessageDigest`类来完成MD5...
1.传递参数: 代码如下: var pmt = ‘sensor=’+ encodeURI(encodeURI(sensor))... top.location.href = ‘jsp/print/diagnosticAnaPrint.jsp?’+pmt; 2.接收和解析参数 代码如下: //获取URL参数 function GetRequest()
### 关于JSP页面间的传参问题 #### JSP页面间传值方法概述 在进行Web开发时,尤其是在使用Java Server Pages(JSP)技术的过程中,页面间的参数传递是一项非常重要的技能。它不仅涉及到基本的HTML知识,还涉及到...
### 在JSP中实现MD5加密 MD5(Message-Digest Algorithm 5)是一种广泛使用的密码散列函数,可以产生一个128位(16字节)的散列值,用于确保信息传输完整一致。MD5算法已被广泛应用于安全领域,如密码存储、数据...