CORS 认为 Access-Control-Allow-Origin 值是通配符,但事实并非如此

问题描述 投票:0回答:1

我正在尝试为我公司的网站创建一个登录系统,并在成功登录后以 cookie 的形式发送刷新令牌。在互联网和 SO 中搜索类似问题后,我有一个可以在本地主机中工作的解决方案,但我无法让它在生产中工作。这是我在生产中遇到的错误:

Access to fetch at 'https://my-linux-api.azurewebsites.net/my-site/login' from origin 'https://www.my-site.com' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

这真是让我费尽心思,因为“Access-Control-Allow-Origin”标头的值绝对不是“*”。这是我在 Node JS api 中的路线:

router.post("/my-site/login", function(req, res) {    
    var email = req.body.Email;
    var password = req.body.Password;
    var connection = new Connection(config);    

    var query = "SELECT * FROM dbo.Users WHERE Email = @email"
    const request = new Request(query,         
        function(err) {            
            connection.close();
            if (err) {
                console.log(err);
                res.send([]);
            }  
        }
    );
    
    request.addParameter('email', TYPES.VarChar, email);

    var result = [];
    connection.connect((err) => {
        if (err) {
            console.log(err);
            res.send(err);
        }
        else
        {            
            request.on('row', function(columns) {                     
                var col = [] 
                columns.forEach((column) => {                      
                    col.push(column.value);
                });                
                result.push(col);                                
            });

            request.on('doneProc', function(rowCount) {                
                if (result.length > 0) {        
                    
                    if (result[0][4] == password) {
                        if (result[0][8] !== 0) {
                            result[0].splice(4, 1);                            
                            const accessPayload = ({ User: result[0], Type: "Authentication" })
                            const accessToken = jwt.sign(accessPayload, process.env.secretKey, { expiresIn: 86400 });

                            const refreshPayload = ({ User: result[0][0], Type: "Refresh" })
                            const refreshToken = jwt.sign(refreshPayload, process.env.secretKey, { expiresIn: 172800 });
                            
                            res.header('Access-Control-Allow-Origin', "https://www.my-site.com");
                            res.header('Access-Control-Allow-Credentials', true);
                            res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
                            res.setHeader('Authorization', `Bearer ${accessToken}`);    
                            res.cookie('refreshToken', refreshToken, {
                                httpOnly: true,
                                secure: true,
                                sameSite: 'Lax',
                                path: "/"                                
                            })                        
                            res.setHeader('Content-Type', 'application/json');
                            res.json({ success: true, message: "Authorization Successful" });                           
                        }
                        else {                            
                            res.sendStatus(403)
                        }
                    }
                    else {
                        res.sendStatus(401);
                    }

                }
                else {
                    res.sendStatus(401)
                }
            })

            request.on('requestCompleted', (rowCount, more)=> {                    
                connection.close();
            })

            connection.execSql(request);  
        }
    })
});

如您所见,我已将“Access-Control-Allow-Origin”标头设置为我的网站名称。我已经检查并仔细检查以确保没有尾随斜杠。

另外,我没有在路线中设置标头,而是尝试使用 cors 包,并将其用作我的路线的参数之一,按照文档:

const cors = require('cors');

const corsOptions = {
    origin: 'https://www.my-site.com',
    credentials: true,
};

router.post("/solutions/login", cors(corsOptions), function(req, res) { ....

我看到有些人说这样的错误是转移注意力,实际问题在其他地方,但事实上,当我将标头设置为“http://localhost:3000”时,它在本地工作,这让我相信没有其他问题。

这是前端代码,供后代使用:

export const Login = (email: string, password: string, context: any) =>
  new Promise(async (resolve, reject) => {
    var formData = new FormData();

    formData.append('Email', email);
    formData.append('Password', password);

    await fetch(url + "my-site/login", {
      method: 'POST',
      credentials: 'include',
      body: formData
    })
    .then((res: any) => {       
      let rawToken = res.headers.get("authorization").split(" ")[1];      
      var accessToken = jwt.decode(rawToken);     
      context.setUser(accessToken.User);
      context.setIsAuthenticated(true);
      localStorage.setItem(
        "authorization",
        rawToken
      )
      if (localStorage.getItem("theme") == null) {
        localStorage.setItem("theme", "light");
      }

      resolve("Success")
    })
    .catch((err) => {
      console.log(err);
      if (err.response.status == 403) {
        reject(403);
      } else if (err.response.status == 401) {
        reject(401);
      } else {
        reject("Error, please try again later");
      }
    })
  });

我不明白如果 CORS 使得这样做如此困难,那么如何约定将刷新令牌存储为 cookie。

提前谢谢您

reactjs node.js express jwt cors
1个回答
0
投票

您在 /my-site/login 上发了帖子,但 cors 已配置为路由 /solutions/login,这是正确的吗?

而且,如果你想实现 cors,请将其添加为每个路由的中间件,如下所示:

const express = require('express');
const cors = require('cors');

const corsOptions = {
  origin: 'https://www.example.com',
  optionsSuccessStatus: 200,
};

const app = express();
app.use(cors(corsOptions));
© www.soinside.com 2019 - 2024. All rights reserved.