Refer to the link
Koa2-cors allows you to specify a single domain name, multiple domain names, and all domain names across domains
When a resource requests a resource from a different domain, protocol, or port than the server on which the resource itself resides, the resource initiates a cross-domain.
CORS
Cross-domain resource sharing
Cross Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to allow Web applications running on one Origin (domain) to access specified resources from different source servers.
cors
Configuration [koa2]
Allows all domain names to be accessed across domains
const cors = require('koa2-cors');
app.use(cors());
Copy the code
Specify a single domain name across domains
app.use(
cors({
origin: function(ctx) { // Set requests from the specified domain to be allowed
return 'http://localhost:8080'; // only requests for http://localhost:8080 are allowed
},
maxAge: 5.// Specifies the validity period of this precheck request, in seconds.
credentials: true.// Whether cookies can be sent
allowMethods: ['GET'.'POST'.'PUT'.'DELETE'.'OPTIONS'].// Sets the allowed HTTP request methods
allowHeaders: ['Content-Type'.'Authorization'.'Accept'].// Set all header fields supported by the server
exposeHeaders: ['WWW-Authenticate'.'Server-Authorization'] // Set to get additional custom fields}));Copy the code
Multiple domain names can be configured across domains
app.use(
cors({
origin: function(ctx) { // Set requests from the specified domain to be allowed
const whiteList = ['http://weipxiu.com'.'http://localhost:8081']; // Cross-domain whitelist
let url = ctx.header.referer.substr(0,ctx.header.referer.length - 1);
if(whiteList.includes(url)){
return url // Note that the domain name cannot end with a /, otherwise it will not succeed, so I killed/via substr earlier
}
return 'http://localhost::3000' // By default, local requests to port 3000 are allowed across domains
},
maxAge: 5.// Specifies the validity period of this precheck request, in seconds.
credentials: true.// Whether cookies can be sent
allowMethods: ['GET'.'POST'.'PUT'.'DELETE'.'OPTIONS'].// Sets the allowed HTTP request methods
allowHeaders: ['Content-Type'.'Authorization'.'Accept'].// Set all header fields supported by the server
exposeHeaders: ['WWW-Authenticate'.'Server-Authorization'] // Set to get additional custom fields}));Copy the code
Problems encountered with withCredentials in the project
Problem description
In the actual project development, we encounter such a problem: after the user logs in successfully, we set a cookie for the user, and when the user visits the web page again, the user information is directly obtained from the cookie. The problem I ran into in the project was that I could not get user information from cookies, and the value I got was undefined
Set after successful logincookie
router.post('/smslogin'.async(ctx,next) => {
// 1. Obtain data
const qqEmail = ctx.request.body.qqEmail;
const pin = ctx.request.body.pin;
console.log(sms)
console.log(qqEmail,pin)
// // 2. Check whether the verification code is correct
if(pin ! = sms) { ctx.body={err_code: 0.message: 'Verification code is not correct! '};
sms = ' '
return;
}
// 3. Query data
let sqlStr = `SELECT * FROM users WHERE qqEmail = '${qqEmail}'`;
let res = await query(sqlStr)
if(res[0]){
ctx.cookies.set('userId', res[0].userId, {
domain: 'localhost'.// Write the domain name of the cookie
path: '/'.// Write the path to the cookie
maxAge: 2 * 60 * 60 * 1000.// Cookie validity period
expires: new Date('2018-02-08'), // Cookie expiration time
httpOnly: false.// Whether to obtain only in HTTP requests
overwrite: false // Whether overwriting is allowed})}else{
ctx.body={err_code:200.message:'Please register and log in! '}}});Copy the code
To obtaincookie
The data in the
router.get('/userinfo'.async(ctx,next) => {
// 1.0 Gets parameters
let userId = ctx.cookies.get('userId') // Failed to get parameters here
let res = await query(`SELECT * FROM users WHERE id = '${userId}'`)
delete res[0].password
ctx.body={
success_code:200.message:res[0]}});Copy the code
Problem analysis
In the case of co-domain, the cookie in the current domain will be carried by default when we send the request, but in the case of cross-domain, the cookie in the request domain will not be carried by default. For example, http://domain-a.com site sends a request for http://api.domain-b.com/get. By default, cookies in the APi.domain-b.com domain are not carried.
In the project, the situation is that the localhost:8080 site receives and sends the localhost:3000 request, and the two ports are different, which constitutes cross-domain. Cross-domain does not carry cookies in the localhost:3000 domain by default.
Problem solving
To solve this problem, we need to make the cross-domain request carry a cookie, which is very simple:
The front-end processing
On the front end I use AXIos to make network requests
axios.defaults.withCredentials = true
Copy the code
The back-end processing
On the back end, we also need to set whether to allow the browser to carry cookie access, which means we need to set the credentials in the response header to true
credentials: true.// Whether cookies can be sent
Copy the code
In addition, we need to configure the CORS. We cannot allow cross-domain access for all domains:
That is, we cannot configure cORS this way.
const cors = require('koa2-cors');
app.use(cors());
Copy the code
The preferred course of action is
Multiple domain names can be configured across domains
app.use(
cors({
origin: function(ctx) { // Set requests from the specified domain to be allowed
const whiteList = ['http://weipxiu.com'.'http://localhost:8081']; // Cross-domain whitelist
let url = ctx.header.referer.substr(0,ctx.header.referer.length - 1);
if(whiteList.includes(url)){
return url // Note that the domain name cannot end with a /, otherwise it will not succeed, so I killed/via substr earlier
}
return 'http://localhost::3000' // By default, local requests to port 3000 are allowed across domains
},
maxAge: 5.// Specifies the validity period of this precheck request, in seconds.
credentials: true.// Whether cookies can be sent
allowMethods: ['GET'.'POST'.'PUT'.'DELETE'.'OPTIONS'].// Sets the allowed HTTP request methods
allowHeaders: ['Content-Type'.'Authorization'.'Accept'].// Set all header fields supported by the server
exposeHeaders: ['WWW-Authenticate'.'Server-Authorization'] // Set to get additional custom fields}));Copy the code
At this point, the problem is solved.
While the problem has been solved, we should also consider why cORS could not be set to allow all domain names to cross domains in the above case.
For security reasons, setting cORS to Allow all domain names to cross domains allows us to obtain the value of the cookie in the back end. There is no problem in the back end, but the server will block the response of Access-Control-Allow-Origin: * for security reasons.