【图文并茂】ant design pro 如何对接后端个人信息接口

在这里插入图片描述

上一节我们有讲到如何对接登录接口的 【图文并茂】ant design pro 如何对接登录接口

仅仅能登录是最基本的,但是我们要进入后台还是需要另一个接口。

这个接口有两个作用:

  1. 来获取当前登录账号的信息,比如头像,用户名,还有一些权限信息等
  2. 来验证一下后台是否登录过

关于第二点,是很重要的,这个接口就是必须你要登录过一次,拿到 token 之后,才能访问到。

如果你没有 token ,也就是说没有登录过,这个接口访问的时候就会出问题,比如你都没登录过,你觉得能拿到个人信息吗,拿谁的。所以没有登录过的,就让它跳到登录页面,就是这个接口的作用。

有没有登录过,就只看浏览器有没有存好 token.

在这里插入图片描述

实现好后端

const getUserProfile = handleAsync(async (req: RequestCustom, res: Response) => {
  // 确保在请求处理流程中间件中已经添加了解析 JWT 并设置 req.user
  const user: IUser | null = await User.findById(req.user?._id)
    .populate('roles') // 预加载 roles 字段
    .exec();

  if (user) {
    // 再次预加载 permissions 字段,因为 roles 已经被预加载
    await user.populate('roles.permissions');

    res.json({
      success: true,
      data: {
        ...exclude(user.toObject(), 'password'),
        avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png',
      },
    });
  } else {
    res.status(404);
    throw new Error('User not found');
  }
});

后端只是把 req.user 的信息拿到并返回给前端罢了。

比如这样的信息:

在这里插入图片描述
那么这个 req.user 是啥

我们看下路由

在这里插入图片描述
前面有个 protect 中间件,这个可以拿到 req.user

它的逻辑是这样的:

const protect = handleAsync(
  async (req: RequestCustom, res: Response, next: NextFunction) => {
    let token;

    if (
      req.headers.authorization &&
      req.headers.authorization.startsWith('Bearer')
    ) {
      try {
        token = req.headers.authorization.split(' ')[1];
        const decoded = jwt.verify(
          token,
          process.env.JWT_SECRET as string,
        ) as jwt.JwtPayload;

        const user: IUser | null = await User.findById(decoded.id)
          .populate({
            path: 'roles',
            populate: {
              path: 'permissions',
              model: 'Permission',
            },
          })
          .exec();

        if (!user || !user.live) {
          throw new Error('User is not live or not found');
        }

        req.user = user;
        console.log('User is', user);
        next();
      } catch (error) {
        console.error(error);
        res
          .status(401)
          .send({ message: error.message || 'Not authorized, token failed' });
      }
    }

    if (!token) {
      res.status(401).send({ message: 'Not authorized, no token' });
    }
  },
);

主要是这里:

req.headers.authorization &&
req.headers.authorization.startsWith(‘Bearer’)

这个地方是从前端拿到头信息。

在这里插入图片描述
下一步就是通过 json web token 的库去解析这个字符串 token 。

    token = req.headers.authorization.split(' ')[1];
    const decoded = jwt.verify(
      token,
      process.env.JWT_SECRET as string,
    ) as jwt.JwtPayload;

拿到里面的 id 再去数据库把当前用户找出来,最后放到 req.user 中。

所以后面的 action 就可以拿到 req.user. 因为 protect 这里已经拿到并存到 req 了。

如果找不到

if (!token) {
  res.status(401).send({ message: 'Not authorized, no token' });
}

就会给前端一个 401 状态码。前端拿到 401 状态码,就会跳出到登录页面。

process.env.JWT_SECRET 上面有个密钥,这是服务器存的,不能暴露出去,就像你家的钥匙一样。

所以我们这个 token 是安全,就算别人伪造了信息,他没有你的 key ,后面也是解析不了,能判断是不是假的数据。

其实最上面 getUserProfile 里的

const user: IUser | null = await User.findById(req.user?._id)
.populate(‘roles’) // 预加载 roles 字段
.exec();

并不是必要的,因为 req.user 应该有 user 的对象记录信息了。当然再查一遍也是没问题。

前端实现

主要是还是在这里:

src/app.tsx

export async function getInitialState(): Promise<{
  settings?: Partial<LayoutSettings>;
  currentUser?: API.CurrentUser;
  loading?: boolean;
  fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
}> {
  const fetchUserInfo = async () => {
    try {
      const response = await queryCurrentUser({
        skipErrorHandler: true,
      });
      return response.data;
    } catch (error) {
      history.push(loginPath);
    }
    return undefined;
  };
  // 如果不是登录页面,执行
  const { location } = history;
  if (location.pathname !== loginPath) {
    const currentUser = await fetchUserInfo();
    return {
      fetchUserInfo,
      currentUser,
      settings: defaultSettings as Partial<LayoutSettings>,
    };
  }
  return {
    fetchUserInfo,
    settings: defaultSettings as Partial<LayoutSettings>,
  };
}

还是跟以前一样,要对接好请求地址,方法,参数

queryCurrentUser

这个逻辑是这样的:

export async function currentUser(options?: { [key: string]: any }) {
  return request<API.CurrentUser>('/auth/profile', {
    method: 'GET',
    ...(options || {}),
  });
}

用的是 get 方法,地址要对。

后面是这个

  const response = await queryCurrentUser({
    skipErrorHandler: true,
  });
  return response.data;

响应的数据要对上

跟这里的数据结构是要对上的API.CurrentUser

  type CurrentUser = {
    isAdmin: CurrentUser | undefined;
    data?: any;
    name?: string;
    avatar?: string;
    role?: string;
    roles?: any;
    _id?: string;
    userid?: string;
    email?: string;
    signature?: string;
    title?: string;
    group?: string;
    tags?: { key?: string; label?: string }[];
    notifyCount?: number;
    unreadCount?: number;
    country?: string;
    access?: string;
    geographic?: {
      province?: { label?: string; key?: string };
      city?: { label?: string; key?: string };
    };
    address?: string;
    phone?: string;
  };

也就是这里的

在这里插入图片描述
这里可能还差一个东西,我们要把 token 提交过去。

我们下一节来讲

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员随风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值