为什么在客户端上 “token” 未定义?

huangapple go评论160阅读模式
英文:

Why is token is undefined on client side?

问题

I make an ecommerce site with nextjs and mongoose using a jwt token in a cookie, going client side in the console, the "application" parameter we can see the cookie which is stored with the name OursiteJWT and it has the value the token:

但经过多次测试后,我们注意到当我检索令牌时,它是未定义的
pages/orders.js :

import { useEffect, useState } from "react";
import axios from "axios";
import jwt from "jsonwebtoken";
import cookie from "cookie";

function Orders() {
  const [orders, setOrders] = useState([]);

  useEffect(() => {
    async function fetchOrders() {
      try {
        // Get the secret from the API
        const secretRes = await axios.get("/api/secret");
        const secret = secretRes.data.secret;
        console.log(secret);
        // Get the JWT token from cookies
        const cookies = cookie.parse(document.cookie);
        const token = cookies.OursiteJWT;
        console.log(token);
        // If the token is not present, redirect to the login page
        if (!token) {
          console.log("No token");
          return;
        }

        // Verify the JWT token
        const decoded = jwt.verify(token, secret);
        const userId = decoded._id;

        // Get user orders from the API
        const ordersRes = await axios.get(`/api/orders?user_id=${userId}`);
        const orders = ordersRes.data;

        setOrders(orders);
      } catch (error) {
        console.error(error);
      }
    }

    fetchOrders();
  }, []);

  return (
    <div>
      {orders.map((order) => (
        <div key={order._id}>
          <h2>Order {order._id}</h2>
          <p>User: {order.name}</p>
          <p>Address: {order.address}</p>
          <p>City: {order.city}</p>
          <p>Products:</p>
          <ul>
            {order.products.map((product) => (
              <li key={product._id}>{product.name}</li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  );
}

export default Orders;

In the console I have "token not found" and the token value is undefined, the secret is correct.

This is how I stored the token:

api/login.js :

import { initMongoose } from "../../lib/mongoose";
import User from '../../models/User';
import { sign } from "jsonwebtoken";
import { serialize } from "cookie";

initMongoose();
const secret = process.env.SECRET;

export default async function handler(req, res) {
  const { email, password } = req.body;
  const user = await User.findOne({ email, password });

  if (!user) {
    res.status(401).json({ message: "Unable to find a user" });
    return;
  } else {
    const token = sign(
      {
        exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30, // 30 days
        email: email,
        _id: user._id,
      },
      secret
    );
    const serialised = serialize("OursiteJWT", token, {
      httpOnly: true,
      secure: process.env.NODE_ENV !== "development",
      sameSite: "strict",
      maxAge: 60 * 60 * 24 * 30,
      path: "/",
    });

    res.setHeader("Set-Cookie", serialised);
    res.status(200).json({ message: "Success!" });
  }
}
英文:

I make an ecommerce site with nextjs and mongoose using a jwt token in a cookie, going client side in the console, the "application" parameter we can see the cookie which is stored with the name OursiteJWT and it has the value the token :

为什么在客户端上 “token” 未定义?

But after several tests we notice that when I retrieve the token it is undefined
pages/orders.js :

import { useEffect, useState } from &quot;react&quot;;
import axios from &quot;axios&quot;;
import jwt from &quot;jsonwebtoken&quot;;
import cookie from &quot;cookie&quot;;

function Orders() {
  const [orders, setOrders] = useState([]);

  useEffect(() =&gt; {
    async function fetchOrders() {
      try {
        // R&#233;cup&#232;re le secret depuis l&#39;API
        const secretRes = await axios.get(&quot;/api/secret&quot;);
        const secret = secretRes.data.secret;
        console.log(secret);
        // R&#233;cup&#232;re le token JWT depuis les cookies
        const cookies = cookie.parse(document.cookie);
        const token = cookies.OursiteJWT;
        console.log(token);
        // Si le token n&#39;est pas pr&#233;sent, redirige vers la page de login
        if (!token) {
          console.log(&quot;pas de token&quot;)
          return;
        }

        // V&#233;rifie le token JWT
        const decoded = jwt.verify(token, secret);
        const userId = decoded._id;

        // R&#233;cup&#232;re les commandes de l&#39;utilisateur depuis l&#39;API
        const ordersRes = await axios.get(`/api/orders?user_id=${userId}`);
        const orders = ordersRes.data;

        setOrders(orders);
      } catch (error) {
        console.error(error);
      }
    }

    fetchOrders();
  }, []);

  return (
    &lt;div&gt;
      {orders.map((order) =&gt; (
        &lt;div key={order._id}&gt;
          &lt;h2&gt;Commande {order._id}&lt;/h2&gt;
          &lt;p&gt;Utilisateur: {order.name}&lt;/p&gt;
          &lt;p&gt;Adresse: {order.address}&lt;/p&gt;
          &lt;p&gt;Ville: {order.city}&lt;/p&gt;
          &lt;p&gt;Produits:&lt;/p&gt;
          &lt;ul&gt;
            {order.products.map((product) =&gt; (
              &lt;li key={product._id}&gt;{product.name}&lt;/li&gt;
            ))}
          &lt;/ul&gt;
        &lt;/div&gt;
      ))}
    &lt;/div&gt;
  );
}

export default Orders;

In the console I have "token not found" and the token value is undefined, the secret is correct.

This is how I stored the token :

api/login.js :

import {initMongoose} from &quot;../../lib/mongoose&quot;;
import User from &#39;../../models/User&#39;;
import { sign } from &quot;jsonwebtoken&quot;;
import { serialize } from &quot;cookie&quot;;



initMongoose()
const secret = process.env.SECRET;

export default async function handler(req,res){
  
  const {email,password}=req.body;
  const user = await User.findOne({email,password});
  
  if(!user){
    res.status(401).json({message: &quot;Impossible de trouver un utilisateur&quot;});
    return;
  }
  else{
    
    const token = sign(
      {
        exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30, // 30 days
        email: email,
        _id: user._id,
      },
      secret
    );
    const serialised = serialize(&quot;OursiteJWT&quot;, token, {
      httpOnly: true,
      secure: process.env.NODE_ENV !== &quot;development&quot;,
      sameSite: &quot;strict&quot;,
      maxAge: 60 * 60 * 24 * 30,
      path: &quot;/&quot;,
    });
    
    res.setHeader(&quot;Set-Cookie&quot;, serialised);
    res.status(200).json({message :&quot;Success!&quot;});
    
    
  }

}

答案1

得分: 1

你无法检索到它的原因是因为你在cookie上设置了httpOnly: true

在生成cookie时使用HttpOnly标志有助于减轻客户端脚本访问受保护的cookie的风险(如果浏览器支持它)。

具有HttpOnly属性的cookie对JavaScript的Document.cookieAPI是不可访问的;它只发送到服务器。例如,存在于服务器端会话中的cookie不需要对JavaScript可用,并且应该具有HttpOnly属性。这个预防措施有助于减轻跨站脚本(XSS)攻击的风险。

详见https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies

英文:

The reason you are unable to retrieve it is because you are setting httpOnly: true on the cookie.

Using the HttpOnly flag when generating a cookie helps mitigate the risk of client side script accessing the protected cookie (if the browser supports it).

> A cookie with the HttpOnly attribute is inaccessible to the JavaScript
> Document.cookie API; it's only sent to the server. For example,
> cookies that persist in server-side sessions don't need to be
> available to JavaScript and should have the HttpOnly attribute. This
> precaution helps mitigate cross-site scripting (XSS) attacks.

see https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies

huangapple
  • 本文由 发表于 2023年1月9日 02:02:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75050171.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定