最近公司写的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