网站跨域问题

什么是跨域问题

       在当前域名请求网站中,默认不允许通过ajax请求发送其他域名。默认情况下浏览器会有安全机制,可以访问,但是获取不到返回结果。

解决方案

  • 使用jsonp解决网站跨域
  • 使用HttpClient内部转发
  • 使用设置响应头允许跨域
  • 基于Nginx搭建企业级API接口网关
  • 使用Zuul搭建微服务API接口网关

jsonp解决网站跨域

$.ajax({
	type : "GET",
	async : false,
	url : "http://b.lun.com:8081/ajaxB",
	dataType : "jsonp",
	jsonp : "jsonpCallback",//服务端用于接收callback调用的function名的参数 
	success : function(data) {
		alert(data["errorCode"]);
	},
	error : function() {
		alert('fail');
	}
});

原理:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。这样说来,这种跨域方式其实与ajax XmlHttpRequest协议无关了。
可以说jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一致的,因为他的原理实际上就是 使用jsscript标签 进行传参,那么必然是get方式的了,和浏览器中敲入一个url一样。

//使用jsonp 解决跨域问题
@RequestMapping("/getBInfo")
public void getBInfo(HttpServletResponse response, String jsonpCallback)
	 throws IOException {
	 JSONObject result = new JSONObject();
	 result.put("retCode", "200");
	 result.put("retMsg", "登陆成功");
	 //获得response的输出流
	 PrintWriter writer = response.getWriter();
	 //拼接jsonpCallback
	 writer.println(jsonpCallback + "(" + result.toJSONString() + ")");
	 //关闭输出流
	 writer.close();
}

使用设置响应头允许跨域

// 该接口提供给A项目进行ajax调用
@RequestMapping("/getBInfo")
public Map<String, Object> getBInfo(HttpServletResponse response) {
	// 告诉客户端(浏览器 )允许跨域访问 *表示所有域名都是可以 在公司中正常的代码应该放入在过滤器中
	response.setHeader("Access-Control-Allow-Origin", "*");
	Map<String, Object> result = new HashMap<String, Object>();
	result.put("retCode", "200");
	result.put("retMsg", "登陆成功");
	return result;
}

一般情况下,会在过滤器下设置响应头。

使用HttpClient进行内部转发

首先先建立一个HttpClient工具包(网上百度了一波)

public class HttpClientUtils {
	private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); // 日志记录

	private static RequestConfig requestConfig = null;

	static {
		// 设置请求和传输超时时间
		requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
	}

	/**
	 * post请求传输json参数
	 * 
	 * @param url
	 *            url地址
	 * @param json
	 *            参数
	 * @return
	 */
	public static JSONObject httpPost(String url, JSONObject jsonParam) {
		// post请求返回结果
		CloseableHttpClient httpClient = HttpClients.createDefault();
		JSONObject jsonResult = null;
		HttpPost httpPost = new HttpPost(url);
		// 设置请求和传输超时时间
		httpPost.setConfig(requestConfig);
		try {
			if (null != jsonParam) {
				// 解决中文乱码问题
				StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				httpPost.setEntity(entity);
			}
			CloseableHttpResponse result = httpClient.execute(httpPost);
			// 请求发送成功,并得到响应
			if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String str = "";
				try {
					// 读取服务器返回过来的json字符串数据
					str = EntityUtils.toString(result.getEntity(), "utf-8");
					// 把json字符串转换成json对象
					jsonResult = JSONObject.parseObject(str);
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			}
		} catch (IOException e) {
			logger.error("post请求提交失败:" + url, e);
		} finally {
			httpPost.releaseConnection();
		}
		return jsonResult;
	}

	/**
	 * post请求传输String参数 例如:name=Jack&sex=1&type=2
	 * Content-type:application/x-www-form-urlencoded
	 * 
	 * @param url
	 *            url地址
	 * @param strParam
	 *            参数
	 * @return
	 */
	public static JSONObject httpPost(String url, String strParam) {
		// post请求返回结果
		CloseableHttpClient httpClient = HttpClients.createDefault();
		JSONObject jsonResult = null;
		HttpPost httpPost = new HttpPost(url);
		httpPost.setConfig(requestConfig);
		try {
			if (null != strParam) {
				// 解决中文乱码问题
				StringEntity entity = new StringEntity(strParam, "utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/x-www-form-urlencoded");
				httpPost.setEntity(entity);
			}
			CloseableHttpResponse result = httpClient.execute(httpPost);
			// 请求发送成功,并得到响应
			if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String str = "";
				try {
					// 读取服务器返回过来的json字符串数据
					str = EntityUtils.toString(result.getEntity(), "utf-8");
					// 把json字符串转换成json对象
					jsonResult = JSONObject.parseObject(str);
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			}
		} catch (IOException e) {
			logger.error("post请求提交失败:" + url, e);
		} finally {
			httpPost.releaseConnection();
		}
		return jsonResult;
	}

	/**
	 * 发送get请求
	 * 
	 * @param url
	 *            路径
	 * @return
	 */
	public static JSONObject httpGet(String url) {
		// get请求返回结果
		JSONObject jsonResult = null;
		CloseableHttpClient client = HttpClients.createDefault();
		// 发送get请求
		HttpGet request = new HttpGet(url);
		request.setConfig(requestConfig);
		try {
			CloseableHttpResponse response = client.execute(request);

			// 请求发送成功,并得到响应
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				// 读取服务器返回过来的json字符串数据
				HttpEntity entity = response.getEntity();
				String strResult = EntityUtils.toString(entity, "utf-8");
				// 把json字符串转换成json对象
				jsonResult = JSONObject.parseObject(strResult);
			} else {
				logger.error("get请求提交失败:" + url);
			}
		} catch (IOException e) {
			logger.error("get请求提交失败:" + url, e);
		} finally {
			request.releaseConnection();
		}
		return jsonResult;
	}

}

通过HttpClient内部转发

// 使用HttpClient进行方法B接口
@RequestMapping("/forWardB")
@ResponseBody
public JSONObject forWardB() {
	JSONObject result = HttpClientUtils.httpGet("http://b.lun.com:8081/getBInfo");
	return result;
}

基于Nginx搭建API接口网关

原理:保证域名和端口号都是相同的,根据项目不同名称使用Nginx进行转发到真实服务器地址。

这种方案可以彻底解决网站跨域问题。

nginx配置文件

server {
        listen       80;
        server_name  www.lun.com;

		###A项目
        location /a {
            proxy_pass   http://a.lun.com:8080/;
            index  index.html index.htm;
        }
		###B项目
		 location /b {
            proxy_pass   http://b.lun.com:8081/;
            index  index.html index.htm;
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值