我的JWT身份验证方法不允许进行Cloudinary上传 [英] Cloudinary upload not allowed with my JWT auth method

查看:96
本文介绍了我的JWT身份验证方法不允许进行Cloudinary上传的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基本上完成了Brad Traversy的Udemy教程"MERN Stack Front To Back",并且遇到了两个类似的错误,试图通过为用户提供使用Cloudinary上传照片的选项来扩展他的应用程序.这两个错误都与CORS请求有关.

I am mostly finished with a Udemy tutorial by Brad Traversy called "MERN Stack Front To Back," and am running into a couple similar errors trying to expand upon his app by giving users the option to upload a photo using Cloudinary. Both errors are related to CORS requests.

在进入该应用之前,了解此应用可能很重要,因为该应用同时使用 npm 运行Node服务器,然后使用相同的npm run dev命令运行React/Redux客户端-且不使用任何中间件来处理CORS请求.所以我的第一个问题是,这种设置如何解决中间件的需求?在我看来,他们仍在运行单独的服务器...

Before getting into it, it might be important to know about this app is that it uses npm Concurrently to run the Node server then the React/Redux client with the same npm run dev command -- and uses no middleware to deal with CORS requests. So my first question is, How does this setup get around the need for the middleware? It seems to me like they're still running separate servers...

无论Brad Traversy的应用为什么没有这种中间件,当我将自己的新操作添加到应用的着陆页时,该操作就以与其他组件相同的方式向api发送请求,例如:

Regardless of why Brad Traversy's app gets away with no such middleware, when I added a new action of my own to the app's landing page that made a request to the api in the same way the other components do, eg:

componentDidMount() {
  this.props.getAllAlerts();
}

export function getAllAlerts() {
  const request = axios.get(`${ROOT_URL}/api/alert`);
  return {
    type: GET_ALL_ALERTS,
    payload: request
  };
}

我收到以下错误: 无法加载 http://localhost:5000/api/alert :对预检请求的响应没有" t通过访问控制检查:所请求的资源上不存在"Access-Control-Allow-Origin"标头起源' http://因此,不允许localhost:3000 '."

I received the following error: "Failed to load http://localhost:5000/api/alert: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access."

我实际上完全通过添加 npm cors 中间件并将其用于我的api服务器.

I actually solved this error entirely simply by adding the npm cors middleware and using it in my api server.

app.use(cors());

还是,我想知道为什么它首先在其他组件不需要api的情况下向api发出axios请求的原因-因为也许它将有助于理解为什么以后在什么时候会遇到非常类似的错误添加一个将照片从浏览器直接上传到Cloudinary的组件.这是动作:

Still, I would like to know why it happened in the first place when the other components do axios requests to the api with no need for it -- because maybe it will help understand why ran into a very similar error later on when adding a component that uploads a photo from the browser directly to Cloudinary. Here's the action:

export const uploadFile = event => {
  const file = event.target.files[0];
  const CLOUDINARY_URL = `https://api.cloudinary.com/v1_1/${myCloudinaryApi}/upload`;
  const CLOUDINARY_UPLOAD_PRESET = CLOUDINARY_UPLOAD_PRESET;
  const formData = new FormData();
  formData.append("file", file);
  formData.append("upload_preset", CLOUDINARY_UPLOAD_PRESET);
  return dispatch => {
    return axios({
      url: CLOUDINARY_URL,
      method: "POST",
      skipAuthorization: true,
      headers: {
        "Content-Type": "application/x-www-form-urlencoded"
      },
      data: formData
    })
      .then(response => {
        dispatch({
          type: UPLOAD_FILE,
          payload: response.data.secure_url
        });
      })
      .catch(function(err) {
        console.log(err);
      });
  };
};

这是错误: 无法加载 https://api.cloudinary.com/v1_1/alertsapi/upload:请求标头字段在飞行前响应中不允许Access-Control-Allow-Headers进行授权."

Here's the error: "Failed to load https://api.cloudinary.com/v1_1/alertsapi/upload: Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response."

即使使用cors中间件,我也不明白为什么会得到这个.

I do not understand why I get this despite using the cors middleware.

最后,出现了一个看起来很相关的皱纹:该应用程序每次加载顶级组件时都会检查JWT令牌:

Finally, an added wrinkle that seems related: This app checks a JWT token every time it loads the top level component:

// Check for token
if (localStorage.jwtToken) {
  // Set auth token header auth
  setAuthToken(localStorage.jwtToken);
  // Decode token and get user info and exp
  const decoded = jwt_decode(localStorage.jwtToken);
  // Set user and isAuthenticated
  store.dispatch(setCurrentUser(decoded));

  // Check for expired token
  const currentTime = Date.now() / 1000;
  if (decoded.exp < currentTime) {
    // Logout user
    store.dispatch(logoutUser());
    // Clear current Profile
    store.dispatch(clearCurrentProfile());
    // Redirect to login
    window.location.href = "/login";
  }
}

class App extends Component {
  render() {
    return ( 
...

如果我取消此检查,则uploadFile操作正常.因此,如果没有其他方法可以解决问题,是否有办法仅针对Cloudinary上传内容绕过此检查?

If I remove this check, the uploadFile action works fine. So if nothing else solves the problem, is there a way to bypass this check for just the Cloudinary upload?

在此先感谢任何人的帮助.让我知道我是否可以提供有关该应用程序的任何其他信息,可能会有所帮助.

Thanks in advance for anyone's help. Let me know if I can provide any additional info about the app that might help.

推荐答案

我想出了第二个问题的解决方案.事实证明, uploadFile 操作中的axios请求包含一个 Authorization 标头,该标头是在我的身份验证检查中通过功能setAuthToken(localStorage.jwtToken)设置的(如上所示).这就是导致上述第二个错误的原因.不幸的是,该功能是从另一个文件导入的,引起了我的注意.在这里:

I figured out a solution to the second question. It turned out that the axios request in the uploadFile action included an Authorization header that was set in my authentication check (shown above) by the function setAuthToken(localStorage.jwtToken). This is what caused the second error mentioned above. Unfortunately, that function was imported from another file and escaped my attention. Here it is:

const setAuthToken = (token`enter code here`) => {
  if (token) {
    // Apply to every request
    axios.defaults.headers.common["Authorization"] = token;
  } else {
    // Delete auth header
    delete axios.defaults.headers.common["Authorization"];
  }
};

Cloudinary请求不允许此标头.要删除我添加的不需要的标题

The Cloudinary request does not allow this header. To remove the unwanted header I added

delete axios.defaults.headers.common["Authorization"]

紧接在 uploadFile 操作中的return dispatch => {行之后.这允许文件成功上载,但是这也意味着,如果另一个axios请求直接跟在此操作之后,它将没有Authorization标头.在这种情况下,下一个动作的确包含了一个要求Authorization标头的axios请求,因此有必要在该操作之前手动将其添加回去:

right after the return dispatch => { line in the uploadFile action. This allowed the file to be uploaded successfully, but it also meant that if another axios request directly followed this action, it would not have the Authorization header. In this case, the next action did include an axios request that required the Authorization header, so it was necessary to add it back manually in that action before the request with this:

axios.defaults.headers.common["Authorization"] = localStorage.jwtToken

第二个问题解决了.我仍然不清楚为什么将我自己的请求添加到相同的api会导致CORS错误.

Second problem solved. I'm still unclear why the addition of my own request to the same api caused a CORS error.

这篇关于我的JWT身份验证方法不允许进行Cloudinary上传的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆