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; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。