从零搭建飞冰微前端项目《第四篇:权限管理》

本文介绍了在Vue项目中实现全局路由拦截和权限管理的详细步骤,包括登录验证、Token管理、路由跳转策略以及错误处理。通过配置请求拦截器和响应拦截器,根据后端返回的状态码判断用户权限,实现无权限、未登录等情况的智能跳转。同时,文章还探讨了路由级和按钮级权限的配置方法,以及未来的工作计划,如颗粒度到按钮的权限控制和请求URL的封装。
摘要由CSDN通过智能技术生成
  • 📢注意:

    • 暂未找到路由全局拦截配置(就是vue-router的路由守卫,解决方案:(无权限,或账号密码错误,或路由错误等)与后端约定,根据报错的状态码,跳到对应报错页面)
    • icestark路由跳转必须使用appHistory!
    • 不细说:配置代理就build.json配置proxy、请求用ice里封装好的request
    • Token里存的用户角色
  • 👦思路:

    • 第一次登录页时,先移除Token(不管有没有),用账号密码发送请求,请求成功跳回主页面,并存储Token
    • 第二次打开页面,如果有Token
      • 有Token,验证是否过期(发checkToken请求)
        • 过期跳转Login登录页
        • 没有过期则允许进入(就不做多余操作)
      • 没有Token,直接跳转Login登录页
    • 路由每次跳转时,验证是否过期(发checkToken请求)
  • ☀️关键:业务上封装统一的请求方法,与服务端约定接口协议,前端根据状态码判断无权限、未登录等状态,然后跳转到指定页面

一.配置全局请求拦截

思路 1 、请求拦截:

  • 如果有token,携带token发请求。

  • 如果没有token,排除主路由外的分组路由(比如忘记密码路由是不用刷新跳回登录页的,但是主页里面的路由刷新如果没有权限需要跳回登录页)之后跳回登录页。

思路 2 、响应拦截:

  • 如果成功,提示成功。

思路 3 、错误拦截:

  • 与后端约定,根据不同status,对应不同权限,渲染不同组件
request: {
    withFullResponse: false,//全局设置 request 是否返回 response 对象,默认为 false-----截取响应数据
    interceptors: {//拦截
        request: {//全局拦截请求
            onConfig: (config) => {
                const accessToken = localStorage.getItem('ACCESS_TOKEN');
                if (accessToken) {
                    config.headers = { Authorization: `Bearer ${accessToken}` } //每次请求携带Token
                } else if (location.pathname !== '/login' && location.pathname !== '/register' && location.pathname !== '/forgotpassword') {//分组路由限制
                    appHistory.push('/login');
                }
                return config;
            }
        },

        response: {//全局拦截响应
            onConfig: (response: any) => {
                const success = response.data.success ? response.data.success : response.data.message === '成功';//还需了解
                if (!success) {
                    // 提示失败信息
                    const { data: { msg } } = response;//连续解构赋值
                    Message.error(msg);
                    return Promise.reject(msg);
                }
                return response.data;
                },
                onError: (error: any) => {//全局拦截请求报错
                    // 业务上封装统一的请求方法,与服务端约定接口协议,前端根据状态码判断无权限、未登录等状态,然后跳转到指定页面。!!!!!!!!!!
                    const status = error.response.status;
                    console.log(status);
                    if (status === 401) {
                        const accessToken = localStorage.getItem('ACCESS_TOKEN');
                        if (accessToken) Message.error("用户身份信息已失效,请重新登录")
                        appHistory.push('/login');// 跳转到登录页面,重新登录(账号密码输入错误的时候)
                    } else if (status === 403) {
                        appHistory.push('/feedback/403');// 跳转到没有权限页面
                    } else if (status === 404) {
                        appHistory.push('/feedback/404');// not found页面
                    } else {
                        appHistory.replace('/login');
                    }
                    return Promise.reject(error);
                }

            },
        }
    },

二、路由级权限配置

路由级(页面级)权限,按钮级权限🎈颗粒度到按钮(后端返回权限数组,判断当前按钮权限字段能否匹配)

  1. 路由级别路由配置使用高阶组件,有app.tsx里的auth判断是否有当前页面权限,没有则不显示(先暂时跳转login)

  2. 目的:配置下面三个就可控制路由级别权限

    • app.tsx配置getInitialData初始化的时候获取权限
    getInitialData: async () => {
        // 业务上封装统一的请求方法,与服务端约定接口协议,前端根据状态码判断无权限、未登录等状态,然后跳转到指定页面。!!!!!!!!!!
        try {
            const data = await request('/user/permission');// 发请求拿权限或者验证权限
            return { auth: data }
        } catch (e) { return { auth: {} } }
    },
    auth: {
        NoAuthFallback: <FeedbackForbidden />,//设置无权限时的展示组件默认为 null
        // 或者传递一个函数组件:NoAuthFallback: () => <div>没有权限..</div>
    },
        //外层的router也需要配菊花!!!
    router: {
        type: 'browser',// 统一History路由
        fallback: <PageLoading />
    },
    
    • 高阶组件:
    //路由高阶组件
    import { useAuth, Redirect } from 'ice';
    
    const LoginWrapper = (WrappedComponent) => {
        const Wrapped = (props) => {
            const [auth] = useAuth();
            console.log(auth,"取到的页面配置auth");
            return <>{auth.isLogin ? <WrappedComponent {...props} /> : <Redirect to="/login" />}</>;
        };
    
        return Wrapped;
    };
    
    export default LoginWrapper;
    
    • 🧡路由匹配高阶组件、这个地方记得组件懒加载(暂时没写报错的路由跳转):
    import { IRouterConfig, lazy } from 'ice';
    import Home from '@/pages/Home';
    import Login from '@/pages/Login';
    import NotFound from '@/components/NotFound';
    import wrapperPage from '@/components/LoginWrapper'
    const Register = lazy(() => import('@/pages/Register'));
    const ForgotPassword = lazy(() => import('@/pages/ForgotPassword/components/StepForm'));
    const Instruction = lazy(() => import('@/pages/Instruction'));
    const routes: IRouterConfig[] = [
        //新的分组路由需要到 layout里的FrameworkLayout、app.tsx里的request 改判断
        {
            path: '/login',//登录
            component: Login,
        },
        {
            path: '/register',//注册
            component: Register,
        },
        {
            path: '/forgotpassword',//忘记密码
            component: ForgotPassword,
        },
        {
            path: '/instruction',//账号说明
            component: Instruction,
        },
        {
            path: '/',//主应用==首页
            exact: true,//精准匹配
            component: Home,
            wrappers: [wrapperPage],
        },
        {
            component: NotFound,
        }
    ];
    export default routes;
    
    

三、按钮级权限配置

正在开发中。。。🤣🤣🤣

四、UI图还没出、原型还没定、配得也差不多了、先写一波页面

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

进度:

  1. 搭好了主应用、微应用
  2. Token管理、请求拦截、代理、表单收集
  3. 路由级权限、菜单配置

下一步:

  1. 颗粒度做到按钮
  2. 请求url尝试封装到一起
  3. 面包屑导航
  4. 简单响应式优化
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值