java servlet手機(jī)app訪問(wèn)接口(一)數(shù)據(jù)加密傳輸驗(yàn)證
前面幾篇關(guān)于servlet的隨筆,算是梳理了servlet的簡(jiǎn)單使用流程,接下去的文章將主要圍繞手機(jī)APP訪問(wèn)接口這塊出發(fā)續(xù)寫,md5加密傳輸--->短信驗(yàn)證--->手機(jī)推送--->分享--->百度云圖---->支付....第三方的業(yè)務(wù) ...由于我是新手我也是一邊學(xué)一邊寫,不足地方希望諒解。
今天這篇文章主要涉及到 javaservlet傳輸數(shù)據(jù)的加密,客戶端請(qǐng)求參數(shù)的組合,并且會(huì)附帶上我中途遇到的所有問(wèn)題以及解決方法。
由于手機(jī)訪問(wèn)接口是公布出來(lái)的,所以不管用什么語(yǔ)言編寫接口,我們就應(yīng)該做相應(yīng)的安全措施,否則人家知道你的URL之后,截獲客戶端的請(qǐng)求,然后修改提交參數(shù),這樣損失就大了。用servlet寫接口用得最多的也應(yīng)該是對(duì)傳輸數(shù)據(jù)進(jìn)行一個(gè)加密,如果是webservice .net的wcf這些這樣的技術(shù)來(lái)編寫,還會(huì)涉及到證書的匹配....
一、請(qǐng)求數(shù)據(jù)參數(shù)的加密與實(shí)現(xiàn)思路。
加密這里我使用的md5 32位的加密,32位是一個(gè)不可逆的加密,這樣即使被黑客截獲了,也是沒(méi)辦法將我們加密后的MD5值,解密成我們加密時(shí)組合的字符串的。 當(dāng)然這個(gè)不是絕對(duì)的,好像前幾年已經(jīng)有計(jì)算機(jī)方面的專家破譯了MD5的加密方式,但我覺(jué)得那技術(shù)首先可能不會(huì)隨意公布出來(lái),然后即使公布了也不是一般人能明白的,否則 你隨便問(wèn)一個(gè)程序員 MD5加密你還在用嗎,那肯定回答是 沒(méi)有了。
1、首先我說(shuō)下我請(qǐng)求參數(shù)的組合思路,因?yàn)檫@里涉及到了MD5加密,所以我們必須在用戶使用APP登錄帳號(hào)之后,反饋給用戶兩個(gè)token,第一個(gè)token是表示用戶身份的唯一值,這個(gè)token是需要增加到請(qǐng)求接口參數(shù)中的(這個(gè)參數(shù)是否參與加密,是你自己定不影響,我這里是參與了的),因?yàn)閟ervlet需要通過(guò)它來(lái)查詢用戶的加密所需token, 第二個(gè)token是用來(lái)加密md5的值,這個(gè)token是不能增加到請(qǐng)求接口參數(shù)中去的,而且這兩個(gè)token我們都必須保存到數(shù)據(jù)庫(kù)中,因?yàn)橛脩粽?qǐng)求接口之后,serlvet需要獲取參數(shù)中的用戶token然后去數(shù)據(jù)庫(kù)中查詢 md5加密所需token,然后servlet再將查詢來(lái)的加密token增加到用戶傳遞來(lái)的字符串中去,再次進(jìn)行一個(gè)md5加密,加密后對(duì)比用戶傳遞的md5加密后的值,是否與servlet加密后的值一樣,如果不一樣,那么原因就可能有兩個(gè),servlet這邊加密字符串組合錯(cuò)誤,用戶傳輸數(shù)據(jù)中途被截修改過(guò)。這兩個(gè)token我都是使用的java uuid生成的,應(yīng)為uuid生成的是一個(gè)唯一值。生成方式很簡(jiǎn)單。下面是代碼
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這邊獲取參數(shù)進(jìn)行加密后,使用加密結(jié)果與用戶請(qǐng)求傳遞的加密結(jié)果進(jìn)行一個(gè)對(duì)比。如果一樣說(shuō)明請(qǐng)求沒(méi)問(wèn)題,否則請(qǐng)求參數(shù)值有可能被修改過(guò)
//下面這個(gè)方法三個(gè)參數(shù) 第一個(gè)是用戶token 第二個(gè)是加密所需要的參數(shù),等會(huì)我們通過(guò)用戶token查詢出 加密token之后,我們需要將它拼接到servlet加密所需json字符串中去,第三個(gè)就是從客戶端傳來(lái)的 加密結(jié)果字符串 這里方法返回0表示 用戶加密后的結(jié)果沒(méi)有問(wèn)題,否則就有錯(cuò)
public static int postTokenVerify(String token, JSONObject requestJsonObject,
String encryptStrValue) {
int returnValue=0;
String[] mysqlParameter=new String[]{token};
//下面就是通過(guò)用戶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) {//說(shuō)明用戶的idToken存在,
// return returnValueString;
//{"idToken":"123456","id":"34","pwd":"23","encryptToken":"2345678","account":"hang"}
/*下面的代碼是在匹配JAVAMD5加密字符串,
因?yàn)橛脩艏用軙r(shí),增加了加密token到加密字符串中去,但是請(qǐng)求時(shí)又不能傳遞這個(gè)加密token,所以我們servlet加密時(shí)需要通過(guò)用戶token去查詢用戶的加密toke, 查詢出來(lái)了,我們就需要拼接到,請(qǐng)求參數(shù)json后面,這樣servlet加密的字符串就與用戶加密的字符串一致了。下面就是查詢出加密token后拼接到請(qǐng)求參數(shù)后面的方法,
*/
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錯(cuò) 誤
}
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
//下面方法就是使用拼接正確的字符串 在servlet上進(jìn)行加密的方法調(diào)用,返回一個(gè)結(jié)果后,對(duì)比用戶傳遞的加密結(jié)果
String javaMd5Result=EncryptSafa.md5Encrypt(byEncryptStrValue);
if (javaMd5Result.equals(encryptStrValue)) {//加密串是正確的
}
else
{
returnValue= 2;//加密結(jié)果有錯(cuò)
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return returnValue;
}
前面都是封裝好的被servlet調(diào)用的方法,下面是servlet頁(yè)調(diào)用的所有代碼
1、請(qǐng)求的URL
這里我是傳遞的是一個(gè)字典轉(zhuǎn)換json格式的參數(shù),是一個(gè)鍵值對(duì)形式,請(qǐng)求參數(shù)只用了一個(gè)。 參數(shù)中的idToken就是用戶token,值我是在數(shù)據(jù)庫(kù)中隨便增加的一個(gè)123456
沒(méi)使用uuid,當(dāng)然正式做肯定不會(huì)這樣。
http://localhost:8080/JAVAServletTest/2.jsp?parameter={"parameter":"{\"idToken\":\"123456\",\"pwd\":\"漢字\",\"account\":\"hang\"}","md5Str":"672f4a8c6fb92103c01d4275e46df790"}
下面是servlet頁(yè)面處理的代碼,整個(gè)流程就是為了驗(yàn)證用戶請(qǐng)求在傳遞的途中是否被修改過(guò)。
//昨天在這里遇到個(gè)問(wèn)題,就是當(dāng)我請(qǐng)求參數(shù)中帶中文時(shí),servlet獲取之后是亂碼的,之后用了下面這種方式好了.
String requestJsonStr=new String(request.getParameter("parameter").getBytes("ISO8859-1"),"UTF-8");
//提交參數(shù)
JSONObject objectParameter=null;
//idToken
JSONObject requestParmeter=null;
//idToken
String idToken="";
//客戶端加密字符串
String md5Str="";
try {
//獲取總的JSON字符串,這里其實(shí)是我們從URL只傳遞的那個(gè)paramter一個(gè)參數(shù)
objectParameter=new JSONObject(requestJsonStr);
//提交參數(shù),json的一個(gè)key值,請(qǐng)求參數(shù)內(nèi)部的paramter,其實(shí)這個(gè)參數(shù)里面放的是業(yè)務(wù)中所需參數(shù),比如你登錄 帳號(hào) 密碼 這類型的
requestParmeter=new JSONObject(objectParameter.getString("parameter"));
//idToken 這個(gè)是用戶token,他就是用戶的唯一標(biāo)識(shí),我們是需要通過(guò)他來(lái)查詢數(shù)據(jù)庫(kù)中對(duì)應(yīng)的 加密token的
idToken=requestParmeter.getString("idToken");
//客戶端加密字符串
md5Str=objectParameter.getString("md5Str");
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//MD5加密后生成的字符串
//下一步是驗(yàn)證token是否正確
int tokenVerifyResult=EncryptSafa.postTokenVerify(idToken, requestParmeter, md5Str);
if (tokenVerifyResult==0) {
out.println("token加密方式正確");
}
else {
out.println("加密token或加密方式錯(cuò)誤");
return;
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis-plus 雙主鍵的實(shí)現(xiàn)示例
本文主要介紹了Mybatis-plus 雙主鍵的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
springcloud?如何解決微服務(wù)之間token傳遞問(wèn)題
這篇文章主要介紹了springcloud?如何解決微服務(wù)之間token傳遞問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Mybatis-Plus實(shí)現(xiàn)自定義SQL具體方法
Mybatis-Plus是Mybatis的一個(gè)增強(qiáng)工具,它可以優(yōu)化我們的開發(fā)效率,這篇文章主要介紹了Mybatis-Plus實(shí)現(xiàn)自定義SQL,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08
WebSocket實(shí)現(xiàn)系統(tǒng)后臺(tái)消息實(shí)時(shí)通知功能
在現(xiàn)代Web應(yīng)用中,提供實(shí)時(shí)通知對(duì)于改善用戶體驗(yàn)至關(guān)重要,WebSocket技術(shù)允許建立雙向通信通道,從系統(tǒng)后臺(tái)將消息實(shí)時(shí)傳送給系統(tǒng)用戶,下面我們就來(lái)深入探討一下如何使用WebSocket來(lái)實(shí)現(xiàn)這一功能吧2023-10-10
Java多線程并發(fā)的指令重排序問(wèn)題及volatile寫屏障原理詳解
這篇文章主要介紹了Java多線程并發(fā)的指令重排序問(wèn)題及volatile寫屏障原理詳解,指令重排序是編譯器或處理器為了提高性能而對(duì)指令執(zhí)行順序進(jìn)行重新排列的優(yōu)化技術(shù),需要的朋友可以參考下2024-01-01

