java servlet 手机 app 访问接口 (一) 数据加密传输验证
这里有新鲜出炉的 Java 设计模式, 程序狗速度看过来!
Java 程序设计语言
java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言, 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台 (即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se)) 的总称
这篇文章主要为大家详细介绍了 java servlet 手机 app 访问接口(一), 数据加密传输验证, 具有一定的参考价值, 感兴趣的小伙伴们可以参考一下
前面几篇关于 servlet 的随笔, 算是梳理了 servlet 的简单使用流程, 接下去的文章将主要围绕手机 APP 访问接口这块出发续写, md5 加密传输 --->短信验证 --->手机推送 --->分享 --->百度云图 ---->支付.... 第三方的业务 ... 由于我是新手我也是一边学一边写, 不足地方希望谅解
今天这篇文章主要涉及到 javaservlet 传输数据的加密, 客户端请求参数的组合, 并且会附带上我中途遇到的所有问题以及解决方法
由于手机访问接口是公布出来的, 所以不管用什么语言编写接口, 我们就应该做相应的安全措施, 否则人家知道你的 URL 之后, 截获客户端的请求, 然后修改提交参数, 这样损失就大了用 servlet 写接口用得最多的也应该是对传输数据进行一个加密, 如果是 webservice .net 的 wcf 这些这样的技术来编写, 还会涉及到证书的匹配....
一请求数据参数的加密与实现思路
加密这里我使用的 md5 32 位的加密, 32 位是一个不可逆的加密, 这样即使被黑客截获了, 也是没办法将我们加密后的 MD5 值, 解密成我们加密时组合的字符串的 当然这个不是绝对的, 好像前几年已经有计算机方面的专家破译了 MD5 的加密方式, 但我觉得那技术首先可能不会随意公布出来, 然后即使公布了也不是一般人能明白的, 否则 你随便问一个程序员 MD5 加密你还在用吗, 那肯定回答是 没有了
1 首先我说下我请求参数的组合思路, 因为这里涉及到了 MD5 加密, 所以我们必须在用户使用 APP 登录帐号之后, 反馈给用户两个 token, 第一个 token 是表示用户身份的唯一值, 这个 token 是需要增加到请求接口参数中的(这个参数是否参与加密, 是你自己定不影响, 我这里是参与了的), 因为 servlet 需要通过它来查询用户的加密所需 token, 第二个 token 是用来加密 md5 的值, 这个 token 是不能增加到请求接口参数中去的, 而且这两个 token 我们都必须保存到数据库中, 因为用户请求接口之后, serlvet 需要获取参数中的用户 token 然后去数据库中查询 md5 加密所需 token, 然后 servlet 再将查询来的加密 token 增加到用户传递来的字符串中去, 再次进行一个 md5 加密, 加密后对比用户传递的 md5 加密后的值, 是否与 servlet 加密后的值一样, 如果不一样, 那么原因就可能有两个, servlet 这边加密字符串组合错误, 用户传输数据中途被截修改过这两个 token 我都是使用的 java uuid 生成的, 应为 uuid 生成的是一个唯一值生成方式很简单下面是代码
- public static String getUUID()
- {
- return UUID.randomUUID().toString();
- }
下面是 java md5 32 位加密方法
- public static String md5Encrypt(String groupParamertStr) throws UnsupportedEncodingException {
- MessageDigest messageDigest = null;
- try {
- messageDigest = MessageDigest.getInstance("MD5");
- messageDigest.reset();
- messageDigest.update(groupParamertStr.getBytes("UTF-8"));
- } catch (NoSuchAlgorithmException e) {
- System.out.println("NoSuchAlgorithmException caught!");
- System.exit(-1);
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- byte[] byteArray = messageDigest.digest();
- StringBuffer md5StrBuff = new StringBuffer();
- for (int i = 0; i < byteArray.length; i++) {
- if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
- md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
- else
- md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
- }
- return md5StrBuff.toString();
- }
下面是 servlet 这边获取参数进行加密后, 使用加密结果与用户请求传递的加密结果进行一个对比如果一样说明请求没问题, 否则请求参数值有可能被修改过
- // 下面这个方法三个参数 第一个是用户 token 第二个是加密所需要的参数, 等会我们通过用户 token 查询出 加密 token 之后, 我们需要将它拼接到 servlet 加密所需 json 字符串中去, 第三个就是从客户端传来的 加密结果字符串 这里方法返回 0 表示 用户加密后的结果没有问题, 否则就有错
- public static int postTokenVerify(String token, JSONObject requestJsonObject, String encryptStrValue) {
- int returnValue = 0;
- String[] mysqlParameter = new String[] {
- token
- };
- // 下面就是通过用户 token 查询 用户的加密 token
- ResultSet returnData = MySqlHepler.executeQuery("select * from infosheet where idToken=?", mysqlParameter);
- JSONObject returnObject = null;
- try {
- returnObject = ResultToJsonTool.resultSetToJsonObject(returnData);
- } catch(SQLException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- } catch(JSONException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- String byEncryptStrValue = "";
- try {
- if (returnObject.getString("encryptToken").length() > 2) { // 说明用户的 idToken 存在,
- // return returnValueString;
- //{"idToken":"123456","id":"34","pwd":"23","encryptToken":"2345678","account":"hang"}
- /* 下面的代码是在匹配 JAVAMD5 加密字符串,
- 因为用户加密时, 增加了加密 token 到加密字符串中去, 但是请求时又不能传递这个加密 token, 所以我们 servlet 加密时需要通过用户 token 去查询用户的加密 toke, 查询出来了, 我们就需要拼接到, 请求参数 json 后面, 这样 servlet 加密的字符串就与用户加密的字符串一致了下面就是查询出加密 token 后拼接到请求参数后面的方法,
- */
- byEncryptStrValue = requestJsonObject.toString().substring(0, requestJsonObject.toString().length() - 1);
- JSONObject encryptTokenJsonObject = new JSONObject();
- encryptTokenJsonObject.put("encryptToken", returnObject.getString("encryptToken"));
- String value1 = encryptTokenJsonObject.toString().substring(1, encryptTokenJsonObject.toString().length());
- byEncryptStrValue = byEncryptStrValue + "," + value1;
- //
- } else {
- returnValue = 1; //idtoken 错 误
- }
- } catch(JSONException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- try {
- // 下面方法就是使用拼接正确的字符串 在 servlet 上进行加密的方法调用, 返回一个结果后, 对比用户传递的加密结果
- String javaMd5Result = EncryptSafa.md5Encrypt(byEncryptStrValue);
- if (javaMd5Result.equals(encryptStrValue)) { // 加密串是正确的
- } else {
- returnValue = 2; // 加密结果有错
- }
- } catch(UnsupportedEncodingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return returnValue;
- }
前面都是封装好的被 servlet 调用的方法, 下面是 servlet 页调用的所有代码
1 请求的 URL
这里我是传递的是一个字典转换 json 格式的参数, 是一个键值对形式, 请求参数只用了一个 参数中的 idToken 就是用户 token, 值我是在数据库中随便增加的一个 123456
没使用 uuid, 当然正式做肯定不会这样
http://localhost:8080/JAVAServletTest/2.jsp?parameter={"parameter":"{\"idToken\":\"123456\",\"pwd\":\" 汉字 \",\"account\":\"hang\"}","md5Str":"672f4a8c6fb92103c01d4275e46df790"}
下面是 servlet 页面处理的代码, 整个流程就是为了验证用户请求在传递的途中是否被修改过
- // 昨天在这里遇到个问题, 就是当我请求参数中带中文时, servlet 获取之后是乱码的, 之后用了下面这种方式好了.
- String requestJsonStr = new String(request.getParameter("parameter").getBytes("ISO8859-1"), "UTF-8");
- // 提交参数
- JSONObject objectParameter = null;
- //idToken
- JSONObject requestParmeter = null;
- //idToken
- String idToken = "";
- // 客户端加密字符串
- String md5Str = "";
- try {
- // 获取总的 JSON 字符串, 这里其实是我们从 URL 只传递的那个 paramter 一个参数
- objectParameter = new JSONObject(requestJsonStr);
- // 提交参数, json 的一个 key 值, 请求参数内部的 paramter, 其实这个参数里面放的是业务中所需参数, 比如你登录 帐号 密码 这类型的
- requestParmeter = new JSONObject(objectParameter.getString("parameter"));
- //idToken 这个是用户 token, 他就是用户的唯一标识, 我们是需要通过他来查询数据库中对应的 加密 token 的
- idToken = requestParmeter.getString("idToken");
- // 客户端加密字符串
- md5Str = objectParameter.getString("md5Str");
- } catch(JSONException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- //MD5 加密后生成的字符串
- // 下一步是验证 token 是否正确
- int tokenVerifyResult = EncryptSafa.postTokenVerify(idToken, requestParmeter, md5Str);
- if (tokenVerifyResult == 0) {
- out.println("token 加密方式正确");
- } else {
- out.println("加密 token 或加密方式错误");
- return;
- }
来源: http://www.phperz.com/article/18/0206/359130.html