java内网环境使用代理访问外网api

java内网环境使用代理访问阿里云api
最近在开发一个app推送功能,我们选用了阿里云和极光的推送接口,在本地有网络的情况都推送成功了,用的阿里云的java_sdk。但是发布测试环境的时候,却推送失败了,是因为服务器属于内网环境,不可直接访问外网接口,所以需要通过代理服务器正向代理访问。

阿里云推送服务文档 https://help.aliyun.com/document_detail/48088.html.

  • 本人通过阿里云官方文档多次测试无果!
    在这里插入图片描述

  • 所以准备不通过sdk的方式,而是通过http直接访问阿里云的open_api
    在翻读阿里云java_sdk的源代码后 找到了用于加密和签名的工具类

  • com.aliyuncs.utils.ParameterHelper.class 时间工具类 获取东八区

  • com.aliyuncs.auth.ShaHmac1.class Hmac-SHA1参数签名工具

  • com.aliyuncs.auth.RpcSignatureComposer.class 重写此方法加密参数获取Signature

maven

		<!--阿里云推送依赖-->
		<dependency>
			<groupId>com.aliyun</groupId>
			<artifactId>aliyun-java-sdk-push</artifactId>
			<version>3.10.0</version>
		</dependency>
		<dependency>
			<groupId>com.aliyun</groupId>
			<artifactId>aliyun-java-sdk-core</artifactId>
			<version>3.2.8</version>
		</dependency>
封装推送Open_Api
    @Value("${xxx.xxx.http.proxyHost:10.1.1.2}")
    private String aliProxyHost; //代理服务器地址

    @Value("${xxx.xxx.http.port:8888}") //代理服务器端口
    private int aliPort; 

    private static final String ALI_URL = "http://cloudpush.aliyuncs.com";

  /**
     * @param queries 推送必传参数,不同系统参数不同
     * @return
     */
    private PushResultDTO pushNotice(Map<String, String> queries) {
        PushResultDTO pushResultDTO = new PushResultDTO();
        String iso8601Time = ParameterHelper.getISO8601Time(new Date());
        queries.put("Format", "XML");
        queries.put("RegionId", regionId);
        queries.put("Version", "2016-08-01");
        queries.put("AccessKeyId", accessKeyId);
        queries.put("SignatureMethod", "HMAC-SHA1");
        queries.put("SignatureNonce", String.valueOf(System.currentTimeMillis()));
        queries.put("SignatureVersion", "1.0");
        queries.put("Timestamp", iso8601Time);
        String StringToSign = composeStringToSign(MethodType.POST, queries);
        System.out.println(StringToSign);
        ShaHmac1 shaHmac1 = new ShaHmac1();
        String secret = "";
        try {
            secret = shaHmac1.signString(StringToSign, accessKeySecret + "&");
            System.out.println(secret);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        queries.put("Signature", secret);
        log.info("开始代理请求 >>>>>>>>>>>>>>>>>>>");
        HttpHost proxy = new HttpHost(aliProxyHost, aliPort);
        String result = httpPostWithParam(ALI_URL, queries, proxy);
        log.info("代理结束{}", result);
        pushResultDTO.setPushMsg(result);
        pushResultDTO.setPushFlag(true);
        return pushResultDTO;
    }

    /**
     * 获取签名 
     * @param method  请求方式
     * @param queries 请求参数
     * @return
     */
    private static String composeStringToSign(MethodType method, Map<String, String> queries) {
        String[] sortedKeys = (String[]) queries.keySet().toArray(new String[0]);
        Arrays.sort(sortedKeys);
        StringBuilder canonicalizedQueryString = new StringBuilder();

        try {
            String[] arr$ = sortedKeys;
            int len$ = sortedKeys.length;

            for (int i$ = 0; i$ < len$; ++i$) {
                String key = arr$[i$];
                canonicalizedQueryString.append("&").append(AcsURLEncoder.percentEncode(key)).append("=").append(AcsURLEncoder.percentEncode((String) queries.get(key)));
            }

            StringBuilder stringToSign = new StringBuilder();
            stringToSign.append(method.toString());
            stringToSign.append("&");
            stringToSign.append(AcsURLEncoder.percentEncode("/"));
            stringToSign.append("&");
            stringToSign.append(AcsURLEncoder.percentEncode(canonicalizedQueryString.toString().substring(1)));
            return stringToSign.toString();
        } catch (UnsupportedEncodingException var13) {
            throw new RuntimeException("UTF-8 encoding is not supported.");
        }
    }

    public static String httpPostWithParam(String url, Map<String, String> map, HttpHost proxy) {
        long startTime = System.currentTimeMillis();
        String returnValue = "";
        CloseableHttpClient httpClient = HttpClients.createDefault();
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        try {
            //第一步:创建HttpClient对象
            httpClient = HttpClients.createDefault();

            //第二步:创建httpPost对象
            HttpPost httpPost = new HttpPost(url);
            RequestConfig requestConfig = RequestConfig.custom()
                    .setProxy(proxy)
                    .build();
            httpPost.setConfig(requestConfig);

            //第三步:给httpPost设置form-data格式的参数
            List params = new ArrayList();
            for (String key : map.keySet()) {
                params.add(new BasicNameValuePair(key, map.get(key)));
            }
            HttpEntity httpEntity = new UrlEncodedFormEntity(params, "UTF-8");
            httpPost.setEntity(httpEntity);

            //第四步:发送HttpPost请求,获取返回值
            returnValue = httpClient.execute(httpPost, responseHandler); //调接口获取返回值时,必须用此方法

        } catch (Exception e) {
            log.warn("异常:", e);
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                log.warn("异常:", e);
            }
            long endTime = System.currentTimeMillis();
            log.debug("http post url: " + url + ",时间秒: " + (double) (endTime - startTime) / 1000 + ",请求参数: "
                    + map + ",返回参数: " + returnValue);
        }
        //第五步:处理返回值
        return returnValue;
    }

推送到ios

/**
*调用自己封装的方法 
*/
public PushResultDTO pushNoticeToSingleIOS(PushUser pushUser, UserDevice userDevice) {
        PushResultDTO pushResultDTO = new PushResultDTO();
        Map<String, String> queries = new LinkedHashMap<>();
        queries.put("AppKey", appKeyIOS);
        queries.put("ApnsEnv", apnsEnv);
        queries.put("Target", TARGET_DEVICE);
        queries.put("TargetValue", userDevice.getDeviceIdAli());
        String title = pushUser.getTitle();
        String body = pushUser.getContent();
        queries.put("Title", title);
        queries.put("Body", body);
        queries.put("Action", ActionEnum.IOS.getDeviceMpush());
	    logger.info("推送开始,ios调用阿里云接口");
        PushResultDTO pushResultDTO1 = pushNotice(queries);
        logger.info("推送结束,ios调用阿里云成功");
        return pushResultDTO1 ;
    }

java技术群: 931243010

### 回答1: 要实现Nginx外网访问内网API,可以采用反向代理的方式。 首先,需要在内网中启动API服务器,并确保其能够在内网环境中正常访问和运行。可以使用任何喜欢的编程语言或框架来编写和部署API服务。 接下来,在位于外网服务器上安装和配置Nginx。Nginx是一个高性能的HTTP和反向代理服务器,可以将外部请求转发到内部API服务器。 首先,需要配置Nginx的基本设置。可以在Nginx的主配置文件中定义服务器的监听端口、域名和其他相关设置。 然后,在Nginx的配置文件中定义反向代理规则,将外网请求转发到内网API服务器的相应地址和端口。可以使用下面的配置示例: ``` server { listen 80; server_name api.example.com; location / { proxy_pass http://内网API服务器的IP地址:端口号; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` 在这个配置示例中,Nginx会监听80端口,并将来自api.example.com域名的请求转发到内网API服务器的对应地址和端口。同时,还设置了一些代理服务器的头信息,以确保内网API服务器能够正确获取客户端的信息。 最后,保存并重新加载Nginx的配置文件,使其生效。可以使用以下命令: ``` sudo nginx -s reload ``` 完成上述步骤后,就可以通过外网访问api.example.com来访问内网API了。Nginx会将外部请求转发到内网API服务器,然后将响应返回给客户端。 需要注意的是,为了确保安全性,可以考虑在Nginx中启用SSL证书,配置HTTPS访问。这样可以对外网访问内网API的通信进行加密,提高数据的安全性。 ### 回答2: Nginx 是一个高性能的开源Web服务器软件和负载均衡器,它通常用于将外部请求转发到内部服务器上的应用程序。要使用Nginx实现外网访问内网API,可以通过以下几个步骤完成。 首先,您需要在内网中部署一个API服务器。这个服务器可以是运行在本地计算机上,也可以是运行在局域网中的某台服务器上。确保API服务器已经配置并可以从内部网络访问。 然后,您需要在具有公网IP的服务器上安装和配置Nginx。这台服务器可以是专门为此目的购买的,或者是您已经拥有并且可以从互联网访问服务器。 接下来,您需要在Nginx的配置文件中添加一个代理配置,将外部请求转发到内网API服务器。在Nginx的配置文件中,您可以使用`proxy_pass`参数指定内网API服务器的IP地址和端口号,如下所示: ``` location /api { proxy_pass http://内网API服务器的IP地址:端口号; } ``` 保存并重启Nginx,使配置生效。 最后,您可以通过使用Nginx服务器的公网IP地址和端口号来访问内网API。只需在浏览器中输入`http://公网IP地址:端口号/api`即可访问。 需要注意的是,在实际部署过程中,还需要根据具体情况进行一些其他配置,例如负载均衡、安全认证等。这样才能确保外网访问内网API的安全和稳定性。 总结来说,使用Nginx实现外网访问内网API是一种常见的解决方案,它可以帮助实现内外网的互通,方便外部用户访问内部的应用程序。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值