1. 程式人生 > >Spring Boot 攔截器 請求引數MD5簽名校驗

Spring Boot 攔截器 請求引數MD5簽名校驗

  1. 攔截器定義
    
    /**
     * 攔截器 請求引數簽名校驗
     * Created by jiyang on 14:47 2017/12/14
     */
    @Component
    @Slf4j
    public class ParameterInterceptor implements HandlerInterceptor {
    
        public static final String VERIFY_FAIL_MSG = "The request parameter signature verification failed!";
    
        @Autowired
        private ChannelService channelService;
    
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
            // 渠道編號
            String channelCode = request.getParameter("channelCode");
            // 簽名
            String signStr = request.getParameter("sign");
    
            if (StringUtils.isBlank(channelCode) || StringUtils.isBlank(signStr)) {
                log.warn(VERIFY_FAIL_MSG);
                response.setStatus(HttpStatus.SC_BAD_REQUEST);
                return false;
            }
    
            Channel channel = channelService.selectByChannelCode(channelCode);
            if (channel == null) {
                log.warn(VERIFY_FAIL_MSG);
                response.setStatus(HttpStatus.SC_BAD_REQUEST);
                return false;
            }
    
            boolean right = MD5Util.verifySign(channel.getEncryptKey(), request);
            if (right) {
                return true;
            }
    
            log.warn(VERIFY_FAIL_MSG);
            response.setStatus(HttpStatus.SC_FORBIDDEN);
            return false;
        }
    
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {
            return ;
        }
    
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
            return ;
        }
    
    }
    

  2. 簽名工具
    
    
    public class MD5Util {
    
        public static String md5(String string) {
            byte[] hash;
            try {
                hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("UTF-8 is unsupported", e);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("MessageDigest不支援MD5Util", e);
            }
            StringBuilder hex = new StringBuilder(hash.length * 2);
            for (byte b : hash) {
                if ((b & 0xFF) < 0x10) hex.append("0");
                hex.append(Integer.toHexString(b & 0xFF));
            }
            return hex.toString();
        }
    
    
        /**
         * md5簽名
         *
         * 按引數名稱升序,將引數值進行連線 簽名
         * @param appSecret
         * @param params
         * @return
         */
        public static String sign(String appSecret, TreeMap<String, String> params) {
            StringBuilder paramValues = new StringBuilder();
            params.put("appSecret", appSecret);
    
            for (Map.Entry<String, String> entry : params.entrySet()) {
                paramValues.append(entry.getValue());
            }
            System.out.println(md5(paramValues.toString()));
            return md5(paramValues.toString());
        }
    
    
        /**
         * 請求引數簽名驗證
         *
         * @param appSecret
         * @param request
         * @return true 驗證通過 false 驗證失敗
         * @throws Exception
         */
        public static boolean verifySign(String appSecret, HttpServletRequest request) throws Exception {
            TreeMap<String, String> params = new TreeMap<String, String>();
    
            String signStr = request.getParameter("sign");
            if(StringUtils.isBlank(signStr)){
                throw new RuntimeException("There is no signature field in the request parameter!");
            }
    
            Enumeration<String> enu = request.getParameterNames();
            while (enu.hasMoreElements()) {
                String paramName = enu.nextElement().trim();
                if (!paramName.equals("sign")) {
                    params.put(paramName, URLDecoder.decode(request.getParameter(paramName), "UTF-8"));
                }
            }
    
            if (!sign(appSecret, params).equals(signStr)) {
                return false;
            }
            return true;
        }
        
    }
    

  3. 新增攔截器
    /**
     * 攔截器
     */
    @Configuration
    public class IntercepterConfig extends WebMvcConfigurerAdapter {
    
        @Value("${longdai.core.token}")
        private String token;
    
        @Value("${app.profile}")
        private String profile;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
    
            //registry.addInterceptor(new SwaggerInterceptor()).addPathPatterns("/v2/api-docs/**");
            // Token 驗證(僅生產)
            if (!("dev".equals(profile.trim()) || "dohko".equals(profile.trim()))) {
                registry.addInterceptor(new TokenInterceptor(token)).addPathPatterns("/**").excludePathPatterns("/health/core/ping");
            }
    
            // 簽名校驗
            registry.addInterceptor(getParameterInterceptor()).addPathPatterns("/v3/thirdParty/**");
        }
    
    
        @Bean
        public HandlerInterceptor getParameterInterceptor(){
            return new ParameterInterceptor();
        }
    }