解决 浏览器同源政策 的方法

方法一 Jsonp 的方式来解决

原理: 利用 script 标签不受同源政策的影响,向服务器端发送请求,返回的是全局函数。

注: 这只是部分代码, 是没有服务器端代码的

<button id="btn1">点我发送请求</button>
	<button id="btn2">点我发送请求</button>
	<script type="text/javascript">
		// 获取按钮
		var btn1 = document.getElementById('btn1');
		var btn2 = document.getElementById('btn2');
		// 为按钮添加点击事件
		btn1.onclick = function () {
		
			// jsonp 是我们封装的函数,调用函数来 发送请求
			jsonp({
				url: 'http://localhost:3001/better',
				success: function (data) {

					console.log(123);
					console.log(data);
				},
				data: {
					name: 'wqx',
					age: 18
				}
			});
		}

		btn2.onclick = function () {
	
			// jsonp 是我们封装的函数,调用函数来 发送请求
			jsonp({
				url: 'http://localhost:3001/better',
				success: function (data) {

					console.log(666);
					console.log(data);
				}
			});
		}

		function jsonp(options) {
			
			// 动态创建 script 标签
			let script = document.createElement('script');

			// 拼接还可以用数组来完成
			// let arr = [];
			// for (let attr in options.data) {
			// 	arr.push(`${attr} = ${options.data[attr]}`);
			// }
			
			// 定义一个空的字符串
			let params = '';
			
			// 循环传递过来的 data 数据
			for (let attr in options.data) {

				params += '&' + attr + '=' + options.data[attr];
			}

			// 生成随机名字, 名字不能相同,不然后续的请求会覆盖前面的请求
			let fnName = 'myjson' + Math.random().toString().replace('.', '');

			// 点后面不能跟变量,所以这里用的就是括号
			// 又因为是全局变量,所以必须要在window下面挂载属性
			window[fnName] = options.success;

			// 拼接参数
			script.src = options.url + '?callback=' + fnName + params;

			document.body.appendChild(script);

			script.onload = function () {

				document.body.removeChild(script);
			}
		}
	</script>

方法二 CORS 解决方法 (主流的解决方式)

前端代码不需要做任何改变
CORS 主要都是后端来解决 跨域 所遇到的问题
// 这些都是后端需要的配置
// 拦截所有请求
app.use((req, res, next) => {
	// 1.允许哪些客户端访问我
	// * 代表允许所有的客户端访问我
	// 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
	res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
	// 2.允许客户端使用哪些请求方法访问我
	res.header('Access-Control-Allow-Methods', 'get,post')
	// 允许客户端发送跨域请求时携带cookie信息
	res.header('Access-Control-Allow-Credentials', true);
	next();
});

方法三 同源政策不会影响服务器

原理: 由一号服务器的 客户端 向一号服务器发出请求,在由 一号服务器 向二号服务器发送请求,这样就解决了同源限制的影响

一号 客户端代码

<button id="btn">点我发送请求</button>
	<script src="/js/ajax.js"></script>
	<script>
		// 获取按钮
		var btn = document.getElementById('btn');
		// 为按钮添加点击事件
		btn.onclick = function () {
			ajax({
				type: 'get',
				url: 'http://localhost:3000/server',
				success: function (data) {
					console.log(data);
				}
			})
		};
	</script>

一号 服务器 后端代码

// 向其他服务器端请求数据的模块
const request = require('request');

app.get('/server', (req, res) => {
	request('http://localhost:3001/cross', (err, response, body) => {
		res.send(body);
	})
});

二号 服务器 后端代码

// 拦截所有请求
app.use((req, res, next) => {
	// 1.允许哪些客户端访问我
	// * 代表允许所有的客户端访问我
	// 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
	res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
	// 2.允许客户端使用哪些请求方法访问我
	res.header('Access-Control-Allow-Methods', 'get,post')
	// 允许客户端发送跨域请求时携带cookie信息
	res.header('Access-Control-Allow-Credentials', true);
	next();
});

app.get('/cross', (req, res) => {
	res.send('ok')
});

方法四 withCredentials 解决跨域登录

客户端代码

<div class="container">
		<form id="loginForm">
			<div class="form-group">
				<label>用户名</label>
				<input type="text" name="username" class="form-control" placeholder="请输入用户名">
			</div>
			<div class="form-group">
				<label>密码</label>
				<input type="password" name="password" class="form-control" placeholder="请输入用密码">
			</div>
			<input type="button" class="btn btn-default" value="登录" id="loginBtn">
			<input type="button" class="btn btn-default" value="检测用户登录状态" id="checkLogin">
		</form>
	</div>
	<script type="text/javascript">
		// 获取登录按钮
		var loginBtn = document.getElementById('loginBtn');
		// 获取检测登录状态按钮
		var checkLogin = document.getElementById('checkLogin');
		// 获取登录表单
		var loginForm = document.getElementById('loginForm');
		// 为登录按钮添加点击事件
		loginBtn.onclick = function () {
			// 将html表单转换为formData表单对象
			var formData = new FormData(loginForm);
			// 创建ajax对象
			var xhr = new XMLHttpRequest();
			// 对ajax对象进行配置
			xhr.open('post', 'http://localhost:3001/login');
			// 当发送跨域请求时,携带cookie信息
			xhr.withCredentials = true;
			// 发送请求并传递请求参数
			xhr.send(formData);
			// 监听服务器端给予的响应内容
			xhr.onload = function () {
				console.log(xhr.responseText);
			}
		}

		// 当检测用户状态按钮被点击时
		checkLogin.onclick = function () {
			// 创建ajax对象
			var xhr = new XMLHttpRequest();
			// 对ajax对象进行配置
			xhr.open('get', 'http://localhost:3001/checkLogin');
			// 当发送跨域请求时,携带cookie信息
			xhr.withCredentials = true;
			// 发送请求并传递请求参数
			xhr.send();
			// 监听服务器端给予的响应内容
			xhr.onload = function () {
				console.log(xhr.responseText);
			}
		}
	</script>

后端代码

app.post('/login', (req, res) => {
	// 创建表单解析对象
	var form = formidable.IncomingForm();
	// 解析表单
	form.parse(req, (err, fields, file) => {
		// 接收客户端传递过来的用户名和密码
		const { username, password } = fields;
		// 用户名密码比对
		if (username == 'itheima' && password == '123456') {
			// 设置session
			req.session.isLogin = true;
			res.send({ message: '登录成功' });
		} else {
			res.send({ message: '登录失败, 用户名或密码错误' });
		}
	})
});

app.get('/checkLogin', (req, res) => {
	// 判断用户是否处于登录状态
	if (req.session.isLogin) {
		res.send({ message: '处于登录状态' })
	} else {
		res.send({ message: '处于未登录状态' })
	}
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值