我项目的Inbox Api如下:
const baseQuery = fetchBaseQuery({
baseUrl: "http://localhost:8000",
});
export const apiSlice = createApi({
baseQuery,
tagTypes: ["User"],
endpoints: (builder) => ({}),
});
我使用apiSlice.injectEndpoints()注入updateUser端点. 更新用户端点如下:
updateUser: builder.mutation({
query: ({ data, token }) => ({
url: `${USERS_URL}/profile`,
method: "PUT",
body: data,
headers: { Authorization: `Bearer ${token}` },
}),
}),
现在,在后台,当用户注册或登录时,我会生成一个令牌.当用户(例如登录)时,响应由用户凭证和令牌组成.登录代码为:
const authUser = asyncHandler(async (req, res) => {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (user && (await user.matchPassword(password))) { // matchPw is a method in user model
const token = generateToken(user._id);
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
token,
});
} else {}});
登录成功后,该操作将通过登录响应进行调度,该响应保存在Inbox存储中为:
const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
setCredentials: (state, action) => {
state.userInfo = action.payload;
AsyncStorage.setItem("userInfo", JSON.stringify(action.payload))
.then(() => console.log("User successfully saved"))
.catch((err) => console.error("Error saving user: ", err));
console.log(state.userInfo)
},
logout: (state) => {
state.userInfo = null
AsyncStorage.removeItem("userInfo")
console.log(state)
}
},
});
现在,在我的reactnative组件(updateuserProfile.jsx)中,我获得userInfo为:
const userInfo = useSelector((state) => state.auth.userInfo);
const token = userInfo.token;
console.log(token)
这将成功注销登录期间创建的令牌.
现在,当updateuserProfile.jsx中的字段被编辑并提交以进行更新时:
const handleSubmit = async () => {
if (password != confirmPassword) {
alert("Passwords donot match");
} else {
try {
console.log("Frontend token: ", token);
const res = await updateUser({
data: {
_id: userInfo._id,
name,
email,
password,
},
token,
}).unwrap();
dispatch(setCredentials({ ...res })); // update the credentials as well
alert("Profile updated");
} catch (err) {
alert(err?.data?.message || err.error);
}
}
};
这里,行console.log("Frontend token: ", token);
也成功注销令牌.
现在将击中的端点是/api/users/profile
.此路由是受保护的路由,因为它需要用户经过身份验证,即用户必须拥有令牌才能更新其个人资料.要保护的路由代码如下:
import jwt from "jsonwebtoken";
import asyncHandler from "express-async-handler";
import User from "../models/userModel.js";
const protect = asyncHandler(async (req, res, next) => {
let token = req.headers.authorization;
console.log("token: ", token);
if (token && token.startsWith("Bearer ")) {
token = token.split(" ")[1];
//if there is a token, we need to verify it
try {
//decode the token
const decoded = jwt.verify(token, process.env.JWT_SECRET); //decoded is a object, that now has a userId field
req.user = await User.findById(decoded.userId).select("-password"); //find the user with the id in the decoded object, as we don't want to return the password we do -password
// doing req.user allows us to access the current user in the protected routes by simply using req.user
next();
} catch (error) {
res.status(401);
throw new Error("Not authorized, invalid token!");
}
} else {
res.status(401);
throw new Error("Not authorized, no token!");
}
});
export { protect };
在第console.log("token: ", token);
行中,我收到的日志(log)是token: Bearer undefined,即我传递headers: { Authorization: `Bearer ${token}` }
的查询,已检测到"Bearer",但"token"保持未定义.