在preHandle中,可以进行编码、安全控制等处理;
在postHandle中,有机会修改ModelAndView;
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。
以下例子用来拦截/local/**的url,并验证签名,只有验证通过的才能进行下一步流程。
在LocalAuthRequestInterceptor中:
package com.zqsign.app.privatearbitrate.interceptor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.zqsign.app.privatearbitrate.model.viewmodel.Response;
import com.zqsign.app.privatearbitrate.util.RsaSign;
import com.zqsign.app.privatearbitrate.util.UrlParamUtil;
import com.zqsign.app.privatearbitrate.util.constants.ZqConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.util.TreeMap;
public class LocalAuthRequestInterceptor extends HandlerInterceptorAdapter {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 验证签名,签名通过放行,否则返回203
* 用客户公钥解密
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("********************服务端请求:{}******************************", request.getRequestURI());
String paramStr = null;
String sign = null;
if (HttpMethod.GET.toString().equals(request.getMethod())) {
TreeMap<String, String> paramMap = UrlParamUtil.paramMap2TreeMap(request.getParameterMap());
paramStr = UrlParamUtil.Map2Str(paramMap);
sign = paramMap.get("sign");
} else {
RepeatedlyReadRequestWrapper requestWrapper = (RepeatedlyReadRequestWrapper) request;
sign = request.getHeader(HttpHeaders.AUTHORIZATION);
if (sign != null) {
Object jsonObject = JSON.parse(this.getBodyString(requestWrapper));
paramStr = JSONObject.toJSONString(jsonObject, SerializerFeature.MapSortField);
}
}
boolean result = verifySign(paramStr, sign);
if (!result) {
response.getWriter().print(JSON.toJSON(Response.error(100,"Request sign error!")));
}
return result;
}
private boolean verifySign(String paramStr, String sign) {
try {
if (sign == null) {
return false;
}
if (paramStr != null && sign != null) {
boolean result = RsaSign.verify(paramStr, sign, ZqConfig.ZQ_PUBLIC_KEY);
return result;
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 获取请求Body
*
* @param request
* @return
*/
private String getBodyString(final ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = cloneInputStream(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();
}
/**
* Description: 复制输入流</br>
*
* @param inputStream
* @return</br>
*/
private InputStream cloneInputStream(ServletInputStream inputStream) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
try {
while ((len = inputStream.read(buffer)) > -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return byteArrayInputStream;
}
}
在spring-mvc.xml的配置:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/local/**"/>
<bean class="com.zqsign.app.privatearbitrate.interceptor.LocalAuthRequestInterceptor" autowire="byType"> </bean>
</mvc:interceptor>
</mvc:interceptors>
在web.xml的配置:
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
说明:此实现是对/local/**的url进行请求拦截,只能签名通过的才能进行请求。