編輯:關於Android編程
今天通過實例來介紹一下如何構建安全的Android客戶端請求,避免非法請求:
服務器端代碼:
代碼1—工具類:
package com.ghj.packageoftool; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Date; /** * 字符串SHA-1轉換 * * @author 高煥傑 */ public class Sha1Util { public static String SHA(String paramString) { MessageDigest localMessageDigest; try { localMessageDigest = MessageDigest.getInstance("SHA-1"); localMessageDigest.update(paramString.getBytes()); return toHexString(localMessageDigest.digest()).toUpperCase(); } catch (NoSuchAlgorithmException localNoSuchAlgorithmException) { localNoSuchAlgorithmException.printStackTrace(); return ""; } } private static String toHexString(byte[] digestArray) { if (digestArray == null || digestArray.length <= 0) { return ""; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < digestArray.length; i++) { String hexString = Integer.toHexString(digestArray[i] & 0xFF); if (hexString.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hexString); } return stringBuilder.toString(); } public static void main(String[] paramArrayOfString) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String timeStamp = dateFormat.format(new Date()); String str = SHA("2014-12-16 10:19:30" + "miyue"); System.out.println(timeStamp + "signature:"+str.equals("927CFBFC8D0F049CEDB83FB10FBEC9AC784A9460")); } }
代碼2—過濾器類:
package com.ghj.packageoffilter; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.ghj.packageoftool.Sha1Util; /** * 本過濾器用來校驗請求是否合法 * * @author 高煥傑 */ public class CheckRequestFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; String secretKey = "AndroidClient"; String timeStamp = request.getParameter("timeStamp"); String signature = request.getParameter("signature"); String dateDifference = getDateDifference(timeStamp); if(dateDifference == null){//系統時間和時間戳的差值為null,這說明該請求中的時間被認為的進行了修改且時間格式不正確。 sendErrorState(response, 0); } if(!Sha1Util.SHA(timeStamp + secretKey).equals(signature)){//如果時間戳被人為地進行了修改造成請求簽名不一致。 sendErrorState(response, 1); }else if(Integer.parseInt(dateDifference) > 1000*60*5){//如果請求從創建到到達服務器端的時間大於5分鐘,則認為請求超時——不給別有用心的人思考的時間 sendErrorState(response, 2); }else{ chain.doFilter(request, response); } } private void sendErrorState(HttpServletResponse response, int errorState) { PrintWriter out = null; try { out = response.getWriter(); out.println("errorState:" + errorState); out.flush(); } catch (IOException e) { e.printStackTrace(); }finally{ out.close(); } return; } /** * @see: 獲取時間戳與當前系統時間的差值(以毫秒為單位) * * @author GaoHuanjie */ private String getDateDifference(String timeStamp){ try{ if(timeStamp != null){ return String.valueOf(new Date().getTime()- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(timeStamp).getTime());//獲取系統時間(毫秒)-時間戳時間(毫秒) } }catch(Exception e){ e.printStackTrace(); } return null; } public void destroy() { } public void init(FilterConfig filterConfig) throws ServletException { } }
代碼3—Servlet類:
package com.ghj.packageofservlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServerServlet extends HttpServlet { private static final long serialVersionUID = -1052048925901833921L; public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain; charset=UTF-8"); request.setCharacterEncoding("UTF-8"); System.err.println(request.getParameter("clientData")); PrintWriter printWriter = response.getWriter(); printWriter.print("您好Android客戶端!"); printWriter.flush(); printWriter.close(); } }
代碼4—配置文件:
checkRequestFilter com.ghj.packageoffilter.CheckRequestFilter checkRequestFilter *.do ServerServlet com.ghj.packageofservlet.ServerServlet ServerServlet /ServerServlet.do
客戶端代碼:
代碼1—工具類:
與服務器端工具類完全一樣!
代碼1—Activity類:
package com.ghj.packageofactivity; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.http.Header; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import com.example.androidclient.R; import com.ghj.packageoftool.Sha1Util; import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.RequestParams; public class AndroidClientActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.android_client); Button sendInfoButton = (Button) findViewById(R.id.sendInfoButton); sendInfoButton.setOnClickListener(new OnClickListener(){ @Override @SuppressLint("SimpleDateFormat") public void onClick(View v) { String secretKey = "AndroidClient"; String timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); RequestParams requestParams = new RequestParams(); requestParams.add("clientData", "您好服務器端!"); requestParams.add("timeStamp", timeStamp); requestParams.add("signature", Sha1Util.SHA(timeStamp + secretKey)); new AsyncHttpClient().post("http://172.16.99.207:8080/CheckRequest/ServerServlet.do", requestParams, new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { if(statusCode == 200){ String responseData = new String(responseBody); if(responseData.contains("errorState")){ Toast.makeText(AndroidClientActivity.this, "請求非法!", Toast.LENGTH_LONG).show(); }else{ Toast.makeText(AndroidClientActivity.this, new String(responseBody), Toast.LENGTH_LONG).show(); } } } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Toast.makeText(AndroidClientActivity.this, "沒有獲取到Android服務器端的響應!", Toast.LENGTH_LONG).show(); } }); } }); } }
總結:
1、由於該Demo客戶端需要依賴很多文件和一些jar包,所以建議直接下載完整Demo工程——【0分下載Demo】
2、實現這個功能其實很簡單:一句話,想盡一切方法讓別有用心的人發出的請求失效!!!
Android小項目藍牙電子鐘 請支持原創,尊重原創,轉載請注明出處:http://blog.csdn.net/kangweijian(來自kangweijian的c
官網地址詳解分析:http://developer.android.com/guide/components/aidl.html一)什麼是AIDL –》 應用
一、效果:我們看到很多軟件的通訊錄在右側都有一個字母索引功能,像微信,小米通訊錄,QQ,還有美團選擇地區等等。這裡我截了一張美團選擇城市的圖片來看看; 我們今天就來實現
使用起來超簡單,如圖: Android Button Maker is online tool to generate button