上一节我们有讲到如何对接登录接口的 【图文并茂】ant design pro 如何对接登录接口
仅仅能登录是最基本的,但是我们要进入后台还是需要另一个接口。
这个接口有两个作用:
- 来获取当前登录账号的信息,比如头像,用户名,还有一些权限信息等
- 来验证一下后台是否登录过
关于第二点,是很重要的,这个接口就是必须你要登录过一次,拿到 token 之后,才能访问到。
如果你没有 token ,也就是说没有登录过,这个接口访问的时候就会出问题,比如你都没登录过,你觉得能拿到个人信息吗,拿谁的。所以没有登录过的,就让它跳到登录页面,就是这个接口的作用。
有没有登录过,就只看浏览器有没有存好 token.
实现好后端
const getUserProfile = handleAsync(async (req: RequestCustom, res: Response) => {// 确保在请求处理流程中间件中已经添加了解析 JWT 并设置 req.userconst 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 提交过去。
我们下一节来讲
- ant design pro 如何去保存颜色
- ant design pro v6 如何做好角色管理
- ant design 的 tree 如何作为角色中的权限选择之一
- ant design 的 tree 如何作为角色中的权限选择之二
- ant design pro access.ts 是如何控制多角色的权限的
- ant design pro 中用户的表单如何控制多个角色
- ant design pro 如何实现动态菜单带上 icon 的
- ant design pro 的表分层级如何处理
- ant design pro 如何处理权限管理
- ant design pro 技巧之自制复制到剪贴板组件
- ant design pro 技巧之实现列表页多标签
- 【图文并茂】ant design pro 如何对接登录接口