对接接口(笔记片段)

这个博客介绍了Java中处理HTTP请求和响应的方法,包括远程调用接口、通过流获取接口返回信息、获取请求真实IP、请求参数模拟及校验等。主要涉及HttpURLConnection和JSON的使用,以及签名验证和IP白名单检查。
摘要由CSDN通过智能技术生成

一、工具方法
1、远程调用接口

/*远程调用
     * requestUrl  请求路径
     * requestMethod   请求方法   POST GET
     * parameter   请求参数
     * obj  请求头设置
     */
  public static String httpsRequest2(String requestUrl, String requestMethod, String parameter,
        Map<String, String> obj) throws IOException {
        log.info("远程调用开始 requestUrl:" + requestUrl + ",requestMethod:" + requestMethod + ",parameter:" + parameter);
        URL connect = null;
        OutputStreamWriter paramout = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        HttpURLConnection connection = null;
        StringBuffer data = new StringBuffer();
        try {
            connect = new URL(requestUrl);
            // 1、打开和url之间的连接
            connection = (HttpURLConnection)connect.openConnection();
            // 2、设置通用的请求属性
            connection.setRequestMethod(requestMethod);// 请求方法post、get
            connection.setDoOutput(true);
            connection.setReadTimeout(30000);
            connection.setConnectTimeout(30000);// 连接超时时间为30秒
            connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
            connection.setRequestProperty("Charset", "UTF-8");
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            if (!ValidateUtil.isNull(obj)) {// 添加请求头参数
                Set<String> keySet = obj.keySet();
                String val;
                for (String key : keySet) {
                    val = obj.get(key);
                    connection.setRequestProperty(key, val);
                }
            }
            if (!ValidateUtil.isNull(parameter)) {
                paramout = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
                paramout.write(parameter);// 请求参数 json数据
                paramout.flush();
            }

            if (HttpURLConnection.HTTP_OK == connection.getResponseCode()
                || HttpURLConnection.HTTP_CREATED == connection.getResponseCode()
                || HttpURLConnection.HTTP_ACCEPTED == connection.getResponseCode()) {
                inputStreamReader = new InputStreamReader(connection.getInputStream(), "UTF-8");
                reader = new BufferedReader(inputStreamReader);
                String line;
                while ((line = reader.readLine()) != null) {
                    data.append(line);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                reader.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            if (paramout != null) {
                paramout.close();
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        log.info("远程调用结束 " + data.toString());
        return data.toString();
    }

2、通过流获取远程接口返回信息

  /*
     * 通过流获取远程调用返回信息
     */
    public static String getHttpParams(HttpServletRequest request) throws IOException {
        StringBuffer sb = new StringBuffer();
        BufferedReader reader = null;
        InputStreamReader inputStreamReader = null;
        try {
            inputStreamReader = new InputStreamReader(request.getInputStream(), "UTF-8");
            reader = new BufferedReader(inputStreamReader);
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (Exception e) {
            log.info("从业务请求中获取参数失败!!!");
            return null;
        } finally {
            if (reader != null) {
                reader.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
        }
        return sb.toString();
    }

3、获取请求真实ip(请求服务器Nginx需要配置)

 location / {
             proxy_pass   http://127.0.0.1:100;
			 proxy_redirect off;          
            proxy_set_header  Host $host;
            proxy_set_header   X-real-ip $remote_addr;
            proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        }
 /*
     * 获取请求真实ip
     */
    public static String httpsRequestIp(HttpServletRequest request) {
        log.info("----------------------获取真实ip开始----------------------------------------");
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                    log.info(InetAddress.getLoopbackAddress() + "");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                ip = inet.getHostAddress();
            }
        }
        log.info("ips:" + ip);
        // 多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        log.info("----------------------获取真实ip结束-----------------------" + ip);
        return ip.trim();
    }

4、请求接口参数模拟

			    Map<String, Object> omap = new HashMap<String, Object>();
                omap.put("partnerOrderNo", "123");// 分销商订单编号
                omap.put("productId", "1");// 三方产品id
                omap.put("goodsId", "2");// 三方商品id
                omap.put("quantity", 1);// 订购份数
                
                long timestamp = new Date().getTime();// 请求时间戳
                String dataString = HttpRequestUtils.jsonToMap(com.alibaba.fastjson.JSONObject.toJSONString(omap));
               
                String sgin = MD5.string2MD5(SystemConfig.APP_SECRET + timestamp + dataString);// 请求签名(请求参数排序签名)
                Map<String, Object> map1 = new HashMap<String, Object>();
                map1.put("appKey", SystemConfig.APP_KEY);
                map1.put("timestamp", timestamp);
                map1.put("sgin", sgin);
                map1.put("data", omap);
                map1.put("otas", "1");
                map1.put("sName", "createOrder_execute");
                String reslut = null;
                try {
                    reslut = CommonUtils.httpsRequest(APIURL, "POST", JSONObject.fromObject(map1).toString());
                } catch (Exception e) {
                    rst.setResult("1");
                    rst.setError("创建订单接口错误");
                    return rst;
                }
              
                JSONObject fromObject = JSONObject.fromObject(reslut);
                if ("200".equals(fromObject.getString("result")) && "0".equals(fromObject.getString("code"))) {
                    datas = fromObject.getJSONObject("message").getJSONObject("data");
                } else {               
                    rst.addMessage("ustate", "1");
                    rst.setError(fromObject.getString("error"));
                    return rst;
                }

5、json字符串转顺序Map

 /**
     * JSON转顺序排序的Map
     *
     * @param jsonStr
     *            原始json
     * @return 响应的map
     */
    public static String jsonToMap(String jsonStr) {
        Map<String, Object> treeMap = new TreeMap();
        com.alibaba.fastjson.JSONObject json =
            com.alibaba.fastjson.JSONObject.parseObject(jsonStr, Feature.OrderedField);// Feature.OrderedField实现解析后保存不乱序
        Iterator<String> keys = json.keySet().iterator();
        while (keys.hasNext()) {
            String key = keys.next();
            Object value = json.get(key);
            // 判断传入kay-value中是否含有""或null
            if (json.get(key) == null || value == null || value.toString().length() == 0) {
                // 当JSON字符串存在null时,不将该kay-value放入Map中,即显示的结果不包括该kay-value
                continue;
            }
            // 判断是否为JSONArray(json数组)
            if (value instanceof JSONArray) {
                JSONArray jsonArray = (JSONArray)value;
                List<Object> arrayList = new ArrayList<>();
                for (Object object : jsonArray) {
                    // 判断是否为JSONObject,如果是 转化成TreeMap
                    if (object instanceof JSONObject) {
                        object = jsonToMap(object.toString());
                    }
                    arrayList.add(object);
                }
                treeMap.put(key, arrayList);
            } else {
                // 判断该JSON中是否嵌套JSON
                boolean flag = isJSONValid(value.toString());
                if (flag) {
                    // 若嵌套json了,通过递归再对嵌套的json(即子json)进行排序
                    value = jsonToMap(value.toString());
                }
                // 其他基础类型直接放入treeMap
                // JSONObject可进行再次解析转换
                treeMap.put(key, value);
            }
        }
        return JSONObject.fromObject(treeMap).toString();
    }

    /**
     * 校验是否是JSON字符串
     *
     * @param json
     *            传入数据
     * @return 是JSON返回true, 否则false
     */
    public final static boolean isJSONValid(String json) {
        try {
            com.alibaba.fastjson.JSONObject.parseObject(json);
        } catch (JSONException ex) {
            return false;
        }
        return true;
    }

6、请求接口校验

    /*request
     * appid
     * timestamp  时间戳
     * sgin  签名
     */
    public static IRestResponse validateRequest(HttpServletRequest request, JSONObject datas) {
        IRestResponse rst = new IRestResponse();
        rst.setResult(IRestResponse.OK);
        rst.setCode("0");
        // 1)获取请求参数
        String appkey = datas.getString("appKey");// 请求APPid
        String timestamp = datas.getString("timestamp");// 请求时间戳
        String sgin = datas.getString("sgin");// 请求签名(请求参数排序签名)
        String data = datas.getString("data");// 业务数据
        // 1)校验请求参数是否为空
        if (ValidateUtil.isNull(appkey)) {
            log.error("缺少appid");
            rst.setCode("1");
            rst.setError("缺少appid");
            return rst;
        }
        if (ValidateUtil.isNull(timestamp)) {
            log.error("缺少时间戳");
            rst.setCode("2");
            rst.setError("缺少时间戳");
            return rst;
        }
        if (ValidateUtil.isNull(sgin)) {
            log.error("缺少签名");
            rst.setCode("4");
            rst.setError("缺少签名");
            return rst;
        }
        // 2) 验证账号是否存在
        AppSecretList app = baseDao.query(AppSecretList.class, "appkey='" + appkey + "' and state='0'", null);
        if (ValidateUtil.isNull(app)) {
            rst.setCode("5");
            rst.setError("无开发者权限");
            return rst;
        }
        if ("1".equals(app.getState())) {
            rst.setCode("6");
            rst.setError("无效appid");
            return rst;
        }
        // 3)验证签名是否有效 (秘钥+时间戳+参数)
        String dataString = "";
        if (!ValidateUtil.isNull(data)) {
            dataString = jsonToMap(data);
        }
        log.info("数据排序" + dataString);
        String sgin1 = MD5.string2MD5(app.getAppsecret() + timestamp + dataString);
        if (!sgin.equals(sgin1)) {
            rst.setCode("11");
            rst.setError("无效签名");
            return rst;
        }
        // 4)验证请求时间是否超时(默认时间戳10秒)
        long times = new Date().getTime();// 当前系统时间戳
        long timestamps = Long.parseLong(timestamp);
        long abstime = Math.abs(times - timestamps);
        if (abstime > 10000) {
            rst.setCode("22");
            rst.setError("数据包已失效");
            return rst;
        }
        // 5)验证是否重复请求
        Object obj = GuavaCacheUtils.get(sgin1);//默认缓存10秒
        if (!ValidateUtil.isNull(obj) && "YES".equals(obj.toString())) {
            rst.setCode("23");
            rst.setError("非法请求");
            return rst;
        } else {
            GuavaCacheUtils.put(sgin1, "YES");
        }
        // 6)验证是否是ip白名单
        if (ValidateUtil.isNull(app.getIps())) {
            rst.setCode("7");
            rst.setError("缺少ip白名单");
            return rst;
        }
        String[] ips = app.getIps().split("\\n");
        String realIp = HttpRequestUtils.httpsRequestIp(request);// 真实请求ip
        log.info("请求ip:" + realIp);
        boolean falg = false;
        for (String ip : ips) {
            log.info("配置白名单" + ip);
            if (realIp.equals(ip.trim())) {
                falg = true;
                break;
            }
        }
        if (!falg) {
            rst.setCode("8");
            rst.setError("非法ip请求");
            return rst;
        }
        // 7)验证是否有接口访问权限
        String msql = "SELECT afm.`methodurl` FROM `app_method_relevance` amr "
            + "INNER JOIN `app_foreign_method` afm ON amr.`methodid`=afm.`id` WHERE amr.`appid`='" + app.getId()
            + "' AND afm.`state`='0'";
        List<Map<String, Object>> mList = baseDao.getList(msql, null);
        if (mList.size() <= 0) {
            rst.setCode("9");
            rst.setError("无接口配置");
            return rst;
        }
        String method = request.getServletPath();
        log.info("请求接口URL:" + method);
        boolean falg1 = false;
        for (Map<String, Object> map : mList) {
            log.info("所有接口" + map.get("methodurl"));
            if (method.equals(map.get("methodurl").toString())) {
                falg1 = true;
                break;
            }
        }
        if (!falg1) {
            rst.setCode("10");
            rst.setError("无接口权限");
            return rst;
        }
        rst.addMessage("appid", app.getId());
        return rst;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值