11package com .company .project .framework .configurer ;
22
33
4+ import org .apache .commons .lang3 .StringUtils ;
5+ import com .alibaba .fastjson .JSON ;
46import com .alibaba .fastjson .serializer .SerializerFeature ;
57import com .alibaba .fastjson .support .config .FastJsonConfig ;
68import com .alibaba .fastjson .support .spring .FastJsonHttpMessageConverter ;
9+ import com .company .project .core .Result ;
10+ import com .company .project .core .ResultCode ;
11+ import org .apache .commons .codec .digest .DigestUtils ;
12+ import org .slf4j .Logger ;
13+ import org .slf4j .LoggerFactory ;
14+ import org .springframework .beans .factory .annotation .Value ;
715import org .springframework .context .annotation .Configuration ;
816import org .springframework .http .MediaType ;
917import org .springframework .http .converter .HttpMessageConverter ;
1018import org .springframework .web .servlet .config .annotation .CorsRegistry ;
19+ import org .springframework .web .servlet .config .annotation .InterceptorRegistry ;
1120import org .springframework .web .servlet .config .annotation .ResourceHandlerRegistry ;
1221import org .springframework .web .servlet .config .annotation .WebMvcConfigurer ;
22+ import org .springframework .web .servlet .handler .HandlerInterceptorAdapter ;
23+
24+ import javax .servlet .http .HttpServletRequest ;
25+ import javax .servlet .http .HttpServletResponse ;
26+ import java .io .IOException ;
1327import java .nio .charset .StandardCharsets ;
28+ import java .util .ArrayList ;
1429import java .util .Arrays ;
30+ import java .util .Collections ;
1531import java .util .List ;
1632
1733/**
2844@ Configuration
2945public class WebMvcConfigurerConfig implements WebMvcConfigurer {
3046
47+ private final Logger logger = LoggerFactory .getLogger (WebMvcConfigurer .class );
48+ @ Value ("${spring.profiles.active}" )
49+ private String env ;//当前激活的配置文件
3150 /**使用阿里 FastJson 作为JSON MessageConverter*/
3251 @ Override
3352 public void configureMessageConverters (List <HttpMessageConverter <?>> converters ) {
@@ -47,7 +66,96 @@ public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
4766 public void addCorsMappings (CorsRegistry registry ) {
4867 registry .addMapping ("/**" );
4968 }
69+ //添加拦截器
70+
71+ @ Override
72+ public void addInterceptors (InterceptorRegistry registry ) {
73+ //接口签名认证拦截器,该签名认证比较简单,实际项目中可以使用Json Web Token或其他更好的方式替代。
74+ if (!"dev" .equals (env )) { //开发环境忽略签名认证
75+ registry .addInterceptor (new HandlerInterceptorAdapter () {
76+ @ Override
77+ public boolean preHandle (HttpServletRequest request , HttpServletResponse response , Object handler ) throws Exception {
78+ //验证签名
79+ boolean pass = validateSign (request );
80+ if (pass ) {
81+ return true ;
82+ } else {
83+ logger .warn ("签名认证失败,请求接口:{},请求IP:{},请求参数:{}" ,
84+ request .getRequestURI (), getIpAddress (request ), JSON .toJSONString (request .getParameterMap ()));
85+
86+ Result result = new Result ();
87+ result .setCode (ResultCode .UNAUTHORIZED ).setMessage ("签名认证失败" );
88+ responseResult (response , result );
89+ return false ;
90+ }
91+ }
92+ });
93+ }
94+ }
95+
96+ private void responseResult (HttpServletResponse response , Result result ) {
97+ response .setCharacterEncoding ("UTF-8" );
98+ response .setHeader ("Content-type" , "application/json;charset=UTF-8" );
99+ response .setStatus (200 );
100+ try {
101+ response .getWriter ().write (JSON .toJSONString (result ));
102+ } catch (IOException ex ) {
103+ logger .error (ex .getMessage ());
104+ }
105+ }
50106
107+ /**
108+ * 一个简单的签名认证,规则:
109+ * 1. 将请求参数按ascii码排序
110+ * 2. 拼接为a=value&b=value...这样的字符串(不包含sign)
111+ * 3. 混合密钥(secret)进行md5获得签名,与请求的签名进行比较
112+ */
113+ private boolean validateSign (HttpServletRequest request ) {
114+ String requestSign = request .getParameter ("sign" );//获得请求签名,如sign=19e907700db7ad91318424a97c54ed57
115+ if (StringUtils .isEmpty (requestSign )) {
116+ return false ;
117+ }
118+ List <String > keys = new ArrayList <String >(request .getParameterMap ().keySet ());
119+ keys .remove ("sign" );//排除sign参数
120+ Collections .sort (keys );//排序
121+
122+ StringBuilder sb = new StringBuilder ();
123+ for (String key : keys ) {
124+ sb .append (key ).append ("=" ).append (request .getParameter (key )).append ("&" );//拼接字符串
125+ }
126+ String linkString = sb .toString ();
127+ linkString = StringUtils .substring (linkString , 0 , linkString .length () - 1 );//去除最后一个'&'
128+
129+ String secret = "Potato" ;//密钥,自己修改
130+ String sign = DigestUtils .md5Hex (linkString + secret );//混合密钥md5
131+
132+ return StringUtils .equals (sign , requestSign );//比较
133+ }
134+
135+ private String getIpAddress (HttpServletRequest request ) {
136+ String ip = request .getHeader ("x-forwarded-for" );
137+ if (ip == null || ip .length () == 0 || "unknown" .equalsIgnoreCase (ip )) {
138+ ip = request .getHeader ("Proxy-Client-IP" );
139+ }
140+ if (ip == null || ip .length () == 0 || "unknown" .equalsIgnoreCase (ip )) {
141+ ip = request .getHeader ("WL-Proxy-Client-IP" );
142+ }
143+ if (ip == null || ip .length () == 0 || "unknown" .equalsIgnoreCase (ip )) {
144+ ip = request .getHeader ("HTTP_CLIENT_IP" );
145+ }
146+ if (ip == null || ip .length () == 0 || "unknown" .equalsIgnoreCase (ip )) {
147+ ip = request .getHeader ("HTTP_X_FORWARDED_FOR" );
148+ }
149+ if (ip == null || ip .length () == 0 || "unknown" .equalsIgnoreCase (ip )) {
150+ ip = request .getRemoteAddr ();
151+ }
152+ // 如果是多级代理,那么取第一个ip为客户端ip
153+ if (ip != null && ip .indexOf ("," ) != -1 ) {
154+ ip = ip .substring (0 , ip .indexOf ("," )).trim ();
155+ }
156+
157+ return ip ;
158+ }
51159 @ Override
52160 public void addResourceHandlers (ResourceHandlerRegistry registry ) {
53161
0 commit comments