標籤:
最近公司寫的android介面需要加密,防止被惡意攻擊。
1 大多數介面加密都是攜帶認證,大家可以參考這位大兄弟的 http://my.oschina.net/jjface/blog/339144
2 這種攜帶認證比較麻煩,而且代碼比較多,比較繁瑣一般同學都搞不定,所以就想了個簡單的辦法,傳兩個參數,一個是string類型的另一種是MD5加密的密文,在服務端寫個攔截器/或者過濾器去攔截他,然後做自己相應的邏輯處理,把string類型的欄位拿過來加上其他一些東西,用MD5加密和傳過來的密文做相應的比較。
3 下面就是重點了,最開始的時候我想到的使用攔截器對url進行攔截,然後做處理,但是我們的服務端不只是對android提供服務介面,還有一些內部的請求,可有時我們的介面是rest風格的,使用resteasy寫的,他的請求方式和springmvc又不太一樣,
@Component
@Path("services")
@Produces({ "application/json"})
@Consumes({ "application/json" })
這種風格的,但是spring的請求是這種風格的
@Controller
@RequestMapping(value = "/../..")
攔截器配置
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/services/**"/> <bean class="*.MyInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
但是這樣配置com.zk.interceptors.MyInterceptor 實現了 HandlerInterceptor介面,可以攔截@RequestMapping註解的類和方法
這樣無法攔截,最後想的辦法是
<mvc:interceptors> <bean class="*.MyInterceptor"></bean> </mvc:interceptors>
這樣把所有的url進行攔截,然後在攔截器自己手動過濾掉不需要攔截的url,對攔截的進行處理,但是最後一想這樣是對所有url進行攔截,肯定對系統的效率有所影響,
4然後想到的是利用切面,自己寫個切面,配置切入點,利用切面的 @Before("execution(* *.*(..))") 通知進行處理。配置切面。具體可以看一些這個
http://www.cnblogs.com/friends-wf/p/3832876.html
5最後完美主義的人不能容忍這樣的事,感覺切面不是很完美,最後想到去攔截器攔截url,過濾器也可以做到這樣的是,可以先看一下兩者的區別
http://www.blogjava.net/hello-yun/archive/2011/11/21/364469.html
在寫過濾器的時候,需要擷取request的參數,get請求servletRequest.getParameter(""),直接這樣寫就可以擷取到,但是最麻煩的是post請求
因為post請求有一些資料會寫入到流中,你需要去流中擷取資料,
/**
* 擷取request流中的資料
* @param request
* @return
* @throws Exception
*/
public String getDate(HttpServletRequest request) throws Exception{
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
這樣資料也可以擷取到了,做到這我以為可以了,但是一測資料得到了,但是在執行不下去,因為你在filter擷取到流中的資料,流中資料只能讀取一次,
你讀完了,業務處理中讀取不到,你需要回寫流中的資料。
package com.imxiaomai.cb.wms.web.filter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* User: liqiang
*/
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request,String data) throws IOException {
super(request);
body = data.getBytes(Charset.forName("UTF-8"));
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
public boolean isFinished() {
return false;
}
public boolean isReady() {
return false;
}
};
}
}
具體的可以看一下這個http://my.oschina.net/vernon/blog/363693
android介面加密