Ajax homology policy

Posted by Danno13 on Fri, 21 Jan 2022 14:20:13 +0100

Ajax request limit: Ajax can only send requests to its own server.

If two pages have the same protocol, domain name and port, the two pages belong to the same source. As long as one of them is different, it is a different source.

For example: http://www.example.com/dir/page.html

  • http://www.example.com/dir2/other.html : homologous http://example.com/dir/other.html : different sources (different domain names)
  • http://v2.www.example.com/dir/other.html : different sources (different domain names)
  • http://www.example.com:81/dir/other.html : different sources (different ports)
  • https://www.example.com/dir/page.html : different sources (different protocols)

Purpose of homology policy: homology policy is to ensure the security of user information and prevent malicious websites from stealing data. The original homology policy refers to the cookies set by website A on the client, and website B cannot be accessed.

With the development of the Internet, the homology policy is becoming more and more strict. In the case of different sources, one of the provisions is that Ajax requests cannot be sent to non homologous addresses. If requested, the browser will report an error.

1, Using JSONP to solve the problem of homology restriction

jsonp is the abbreviation of json with padding. It does not belong to Ajax requests, but it can simulate Ajax requests.

1. Write the server-side request address of different origin in the src attribute of the script tag

 <script src="www.example.com"></script>//Using the characteristics of script tags, it is not affected by the homology policy
 <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

2. The server-side response data must be a function call, and the data really sent to the client needs to be used as the parameters of the function call.

 const data = 'fn({name: "Zhang San", age: "20"})';
 res.send(data);

3. Define the function fn under the global scope of the client

 function fn (data) { }

4. Process the data returned by the server inside the fn function

 function fn (data) { console.log(data); }

JSONP code optimization

  1. The client needs to pass the function name to the server.
  2. Turn the sending of script request into dynamic request.
  3. Encapsulate jsonp functions to facilitate request sending.
  4. res.jsonp method for server-side code optimization.

Case: using jsonp to obtain Tencent weather information

 . html code

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>use jsonp Get Tencent weather information</title>
	<link rel="stylesheet" href="/assets/bootstrap/dist/css/bootstrap.min.css">
	<style type="text/css">
		.container {
			padding-top: 60px;
		}
	</style>
</head>
<body>
	<div class="container">
		<table class="table table-striped table-hover" align="center" id="box"></table>
	</div>
	<script src="/js/jsonp.js"></script>
	<script src="/js/template-web.js"></script>
	<script type="text/html" id="tpl">
		<tr>
			<th>time</th>
			<th>temperature</th>
			<th>weather</th>
			<th>wind direction</th>
			<th>wind power</th>
		</tr>
		{{each info}}
		<tr>
			<td>{{dateFormat($value.update_time)}}</td>
			<td>{{$value.degree}}</td>
			<td>{{$value.weather}}</td>
			<td>{{$value.wind_direction}}</td>
			<td>{{$value.wind_power}}</td>
		</tr>
		{{/each}}
	</script>
	<script>
		// Get table tag
		var box = document.getElementById('box');

		function dateFormat(date) {
			var year = date.substr(0, 4);
			var month = date.substr(4, 2);
			var day = date.substr(6, 2);
			var hour = date.substr(8, 2);
			var minute = date.substr(10, 2);
			var seconds = date.substr(12, 2);
			return year + 'year' + month + 'month' + day + 'day' + hour + 'Time' + minute + 'branch' + seconds + 'second';
		}

		// Opening external variables to templates
		template.defaults.imports.dateFormat = dateFormat;

		// Obtain weather information from the server
		jsonp({
			url: 'https://wis.qq.com/weather/common ', / / request address
			data: {
				source: 'pc',
				weather_type: 'forecast_1h',//Next 48 hours
				// weather_type: 'forecast_1h|forecast_24h ', / / next 48 hours | next 7 days
				province: 'Heilongjiang Province',
				city: 'Harbin City'
			},
			success: function (data) {
				var html = template('tpl', {info: data.data.forecast_1h});
				box.innerHTML = html;
			}
		})
	</script>
</body>
</html>

app.js code

// Introducing express framework
const express = require('express');
// Path processing module
const path = require('path');
// A module that requests data from other servers
const request = require('request');
// Create web server
const app = express();
// Static resource access service function
app.use(express.static(path.join(__dirname, 'public')));

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

// Listening port
app.listen(3000);
// Console prompt output
console.log('The server started successfully');

2, CORS cross domain resource sharing

CORS: the full name is cross origin resource sharing, that is, cross domain resource sharing. It allows browsers to send Ajax requests to cross domain servers, overcoming the limitation that Ajax can only be used from the same source. If the server agrees to the request, it will add {access control allow origin in the response header. If it does not agree, it will not add.

 origin: http://localhost:3000
//There are two types that may be returned: 1. The original information of the client; 2. The asterisk* 
Access-Control-Allow-Origin: 'http://localhost:3000'
Access-Control-Allow-Origin: '*'

Example code of setting response header on Node server side:

 app.use((req, res, next) => {
     res.header('Access-Control-Allow-Origin', '*');
     res.header('Access-Control-Allow-Methods', 'GET, POST');
     next();
 })

3, Accessing non homologous data - server side solution

The homology policy is the restriction of Ajax technology given by the browser, and there is no homology policy restriction on the server.

4, Cookies

Equivalent to ID card, which can confirm who the client is.

withCredentials property

  • When sending a cross domain request using Ajax technology, cookie information will not be carried in the request by default.
  • withCredentials: Specifies whether to carry cookie information when cross domain requests are involved. The default value is false
  • (field carried in response header) access control allow credentials: true allows the client to carry cookie s when sending requests

Case: simulate cross domain login function

html code

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Realize cross domain function</title>
	<link rel="stylesheet" href="/assets/bootstrap/dist/css/bootstrap.min.css">
	<style type="text/css">
		.container {
			padding-top: 60px;
		}
	</style>
</head>
<body>
	<div class="container">
		<form id="loginForm">
			<div class="form-group">
				<label>user name</label>
				<input type="text" name="username" class="form-control" placeholder="enter one user name">
			</div>
			<div class="form-group">
				<label>password</label>
				<input type="password" name="password" class="form-control" placeholder="Please enter your password">
			</div>
			<input type="button" class="btn btn-default" value="Sign in" id="loginBtn">
			<input type="button" class="btn btn-default" value="Detect user login status" id="checkLogin">
		</form>
	</div>
	<script type="text/javascript">
		// Get login button
		var loginBtn = document.getElementById('loginBtn');
		// Get detection login status button
		var checkLogin = document.getElementById('checkLogin');
		// Get login form
		var loginForm = document.getElementById('loginForm');
		// Add click event for login button
		loginBtn.onclick = function () {
			// Convert html form to formData form object
			var formData = new FormData(loginForm);
			// Creating ajax objects
			var xhr = new XMLHttpRequest();
			// Configuring ajax objects
			xhr.open('post', 'http://localhost:3001/login');
			// When a cross domain request is sent, the cookie information is carried
			xhr.withCredentials = true;
			// Send request and pass request parameters
			xhr.send(formData);
			// Listen for the response given by the server
			xhr.onload = function () {
				console.log(xhr.responseText);
			}
		}

		// When the detect user status button is clicked
		checkLogin.onclick = function () {
			// Creating ajax objects
			var xhr = new XMLHttpRequest();
			// Configuring ajax objects
			xhr.open('get', 'http://localhost:3001/checkLogin');
			// When a cross domain request is sent, the cookie information is carried
			xhr.withCredentials = true;
			// Send request and pass request parameters
			xhr.send();
			// Listen for the response given by the server
			xhr.onload = function () {
				console.log(xhr.responseText);
			}
		}
	</script>
</body>
</html>

app.js

// Introducing express framework
const express = require('express');
// Path processing module
const path = require('path');
// Receive post request parameters
const formidable = require('formidable');
// Realize session function
var session = require('express-session');
// Create web server
const app = express();
// Receive post request parameters
// Realize session function
app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: false
}));

// Static resource access service function
app.use(express.static(path.join(__dirname, 'public')));

// Block all requests
// app.use((req, res, next) => {
// 	// 1. Which clients are allowed to access me
// 	//* allow all clients to access me
// 	res.header('Access-Control-Allow-Origin', '*')
// 	// 2. What request methods are allowed for clients to access me
// 	res.header('Access-Control-Allow-Methods', 'get,post')
// 	next();
// });

app.get('/test', (req, res) => {
	const result = 'fn({name: "Zhang San"})';
	res.send(result);
});

app.get('/better', (req, res) => {
	// The name of the function passed from the receiving client
	//const fnName = req.query.callback;
	// Return the function call code corresponding to the function name to the client
	//const data = JSON.stringify({name: "Zhang San"});
	//const result = fnName + '('+ data +')';
	// setTimeout(() => {
	// 	res.send(result);
	// }, 1000)
	res.jsonp({name: 'lisi', age: 20});
});

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

// Block all requests
app.use((req, res, next) => {
	// 1. Which clients are allowed to access me
	// *Allow all clients to access me
	// Note: if cookie information transfer is involved in the cross domain request, the value cannot be * sign, such as specific domain name information
	res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
	// 2. What request methods are allowed for clients to access me
	res.header('Access-Control-Allow-Methods', 'get,post')
	// Allow the client to carry cookie information when sending cross domain requests
	res.header('Access-Control-Allow-Credentials', true);
	next();
});

app.post('/login', (req, res) => {
	// Create form resolution object
	var form = formidable.IncomingForm();
	// Parse form
	form.parse(req, (err, fields, file) => {
		// Receive the user name and password passed by the client
		const { username, password } = fields;
		// User name password comparison
		if (username == 'itheima' && password == '123456') {
			// Set session
			req.session.isLogin = true;
			res.send({message: 'Login succeeded'});
		} else {
			res.send({message: 'Login failed, Wrong user name or password'});
		}
	})
});

app.get('/checkLogin', (req, res) => {
	// Judge whether the user is logged in
	if (req.session.isLogin) {
		res.send({message: 'Is logged in'})
	} else {
		res.send({message: 'Not logged in'})
	}
});


// Listening port
app.listen(3001);
// Console prompt output
console.log('The server started successfully');

Topics: Javascript Ajax server