摘要:以上為加解密在實際開發過程中代碼,代碼提交是對于和等符號進行過濾,防止注入,在開發過程中可以參考此代碼進行適當修改進行使用
web開發過程中對post請求過來的整個請求流數據,怎樣保證post在傳輸過程中被截取后無法獲取到用戶提交請求實際數據,保證請求安全,在實踐過程中我們采用過濾器(Filter)來實現流截取完成這個代碼post請求流數據及返回數據加解密
一、請求數據流解密1 請求數據提交filter進行數據過濾,過濾器類主要用于創建HttpServletRequest,實現解密,將解密后的request返回到下層
public class CharacterFilter implements Filter{ @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)req; TsRequest wrapRequest= new TsRequest(request,request.getParameterMap()); chain.doFilter(wrapRequest, res); } }
2、提交數據解密:前端或者app端對提交數據流數據解密,繼承HttpServletRequestWrapper方法實現自己的HttpServletRequest,拷貝原始數據流,getParameterValues寫入解密方法,Spring框架進行自動解包是會通過getParameterValues讀取數據流,進行自動解包,將數據set到對象,完成數據解密過程(copy數據流主要解決流只能讀取一次問題)
public class TsRequest extends HttpServletRequestWrapper{ private Map params; public static final int BUFFER_SIZE = 4096; private byte[] requestBody = null; public TsRequest(HttpServletRequest request, Map newParams) { super(request); this.params = newParams; // 緩存請求body 讀取Post數據 String method = request.getMethod(); if (("POST").equals(request.getMethod())) { try { ByteArrayOutputStream out = copy(request.getInputStream()); requestBody = out.toByteArray(); } catch (IOException e) { e.printStackTrace(); } } } public static ByteArrayOutputStream copy(InputStream in) throws IOException { String data = convertStreamToString(in); if (data != null && data.indexOf("time") == -1) { try { data = AESDataUtils.decrypt(data); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } byte bytes[] = data.getBytes("UTF-8"); ByteArrayOutputStream out = new ByteArrayOutputStream(bytes.length); out.write(bytes, 0, bytes.length); out.flush(); return out; } public static String convertStreamToString(InputStream is) throws UnsupportedEncodingException { BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } /** * 重寫 getInputStream() */ @Override public ServletInputStream getInputStream() throws IOException { if (requestBody == null) { requestBody = new byte[0]; } final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); } }; } /** * 重寫 getReader() */ @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } public Map getParameterMap() { return params; } public Enumeration getParameterNames() { Vector l = new Vector(params.keySet()); return l.elements(); } public String[] getParameterValues(String name) { Object v = params.get(name); if (v == null) { return null; } else if (v instanceof String[]) { String[] value = (String[]) v; for (int i = 0; i < value.length; i++) { // AES解密數據 value[i]=AESDataUtils.decrypt(value[i]); if (StringUtils.isNoneEmpty(value[i])) { value[i] = value[i].replaceAll("<", "<"); value[i] = value[i].replaceAll(">", ">"); } } return (String[]) value; } else if (v instanceof String) { String value = (String) v; value=AESDataUtils.decrypt(value); // AES解密數據 if (StringUtils.isNoneBlank(value)) { value = value.replaceAll("<", "<"); value = value.replaceAll(">", ">"); } return new String[] { (String) value }; } else { return new String[] { v.toString() }; } } public String getParameter(String name) { Object v = params.get(name); if (v == null) { return null; } else if (v instanceof String) { String value = (String) v; value = AESDataUtils.decrypt(value); // AES解密數據 if (StringUtils.isNoneBlank(value)) { value = value.replaceAll("<", "<"); value = value.replaceAll(">", ">"); } return (String) value; } else if (v instanceof String[]) { String[] strArr = (String[]) v; if (strArr.length > 0) { String value = strArr[0]; String aesdata=AESDataUtils.decrypt(value); if(StringUtils.isNoneEmpty(aesdata)){ value =aesdata ; } // AES解密數據 if (StringUtils.isNoneBlank(value)) { value = value.replaceAll("<", "<"); value = value.replaceAll(">", ">"); } return value; } else { return null; } } else { return v.toString(); } } }二、返回數據流加密
1、繼承過濾器接口實現返回數據過濾攔截,將返回數據轉換為代理類,通過代理類改變處理返回數據流進行加密并將加密后數據重新寫入到流中返回(使用代理類主要是為了解決流只能讀取一次問題)
public class ResponseFilter implements Filter{ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(request, response); ResponseWrapper wrapperResponse = new ResponseWrapper( (HttpServletResponse) response);// 轉換成代理類 // 這里只攔截返回,直接讓請求過去,如果在請求前有處理,可以在這里處理 filterChain.doFilter(request, wrapperResponse); byte[] content = wrapperResponse.getContent();// 獲取返回值 if (content.length > 0) { String str = new String(content, "UTF-8"); String ciphertext = null; try { ciphertext = AESDataUtils.encrypt(str); // ......根據需要處理返回值 } catch (Exception e) { e.printStackTrace(); } //將加密后數據重新寫如后刷新數據流 ServletOutputStream out = response.getOutputStream(); out.write(ciphertext.getBytes()); out.flush(); } } }
2.返回值輸出代理,通過代理獲取返回值信息內容
public class ResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream buffer; private ServletOutputStream out; public ResponseWrapper(HttpServletResponse httpServletResponse) { super(httpServletResponse); buffer = new ByteArrayOutputStream(); out = new WrapperOutputStream(buffer); } @Override public ServletOutputStream getOutputStream() throws IOException { return out; } @Override public void flushBuffer() throws IOException { if (out != null) { out.flush(); } } public byte[] getContent() throws IOException { flushBuffer(); return buffer.toByteArray(); } class WrapperOutputStream extends ServletOutputStream { private ByteArrayOutputStream bos; public WrapperOutputStream(ByteArrayOutputStream bos) { this.bos = bos; } @Override public void write(int b) throws IOException { bos.write(b); } } }三、使用工具類代碼
AES加密工具類加解密代碼模塊,主要http請求加密過程會進行URL編碼傳入,需要進行URLDecoder.decode進行解碼后才能進行解密操作
public class AESDataUtils { /** * 解密 * @param value * @return */ public static String decrypt(String value){ if(StringUtils.isNoneEmpty(value)){ if(value.indexOf("%")>-1){ value=URLDecoder.decode(value); } } try { return AESUtils.decrypt(value); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 加密 * @param value * @return */ public static String encrypt(String value){ value=AESUtils.encrypt(value); value=URLEncoder.encode(value); return value; } }
實際AES加解密代碼塊,本文檔采用aes進行加密,也可以自行可以換其它加密方式進行加密
public class AESUtils { private static String secretKey = "秘鑰"; private static String ivParameter = ""; /** * aes 解密 * * @param sSrc * @return * @throws Exception */ public static String decrypt(String sSrc) throws Exception { try { byte[] raw = secretKey.getBytes("ASCII"); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES / CBC / PKCS5Padding"); IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes()); cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);// 先用base64解密 byte[] original = cipher.doFinal(encrypted1); String originalString = new String(original, "UTF-8"); return originalString; } catch (Exception ex) { return null; } } //加密 public static String encrypt(String sSrc) { try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] raw = secretKey.getBytes(); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); //使用CBC模式,需要一個向量iv,可增加加密算法的強度 IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8")); //此處使用BASE64做轉碼。 return new BASE64Encoder().encode(encrypted); } catch (Exception ex) { return null; } } }
以上為加解密在實際開發過程中代碼,代碼提交是對于>和<等符號進行過濾,防止sql注入,在開發過程中可以參考此代碼進行適當修改進行使用
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71066.html
摘要:以上為加解密在實際開發過程中代碼,代碼提交是對于和等符號進行過濾,防止注入,在開發過程中可以參考此代碼進行適當修改進行使用 web開發過程中對post請求過來的整個請求流數據,怎樣保證post在傳輸過程中被截取后無法獲取到用戶提交請求實際數據,保證請求安全,在實踐過程中我們采用過濾器(Filter)來實現流截取完成這個代碼post請求流數據及返回數據加解密 一、請求數據流解密 1 請求...
摘要:今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...
摘要:今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...
摘要:于是便誕生了隨行付分布式文件系統簡稱,提供的海量安全低成本高可靠的云存儲服務。子系統相關流程圖如下核心實現主要為隨行付各個業務系統提供文件共享和訪問服務,并且可以按應用統計流量命中率空間等指標。 背景 傳統Web應用中所有的功能部署在一起,圖片、文件也在一臺服務器;應用微服務架構后,服務之間的圖片共享通過FTP+Nginx靜態資源的方式進行訪問,文件共享通過nfs磁盤掛載的方式進行訪問...
摘要:本文則主要總結了心悅俱樂部的接入層從文本協議到二進制協議迭代過程中的技術方案,包括協議規范安全性等方面的內容。在心悅的文本協議方案中,采用的是對請求數據進行模式的加密。包括明文的協議包頭和密文的二進制流。 歡迎大家前往騰訊云+社區,獲取更多騰訊海量技術實踐干貨哦~。 作者:羅廣鎮 | 騰訊移動開發工程師 App與后臺通信通常有采用json等文本協議或者采用二進制協議,本文則主要總結了心...
閱讀 3917·2021-09-09 09:33
閱讀 1773·2021-09-06 15:14
閱讀 1919·2019-08-30 15:44
閱讀 3075·2019-08-29 18:36
閱讀 3765·2019-08-29 16:22
閱讀 2095·2019-08-29 16:21
閱讀 2530·2019-08-29 15:42
閱讀 1648·2019-08-29 11:00