想用 nextjs+swr+Material-UI 做个后台管理系统,请问路由守卫和用户鉴权如何做比较好呢?

2022-01-03 11:04:33 +08:00
 sciel

大家好,我想用 nextJs 做个后台管理系统。但路由守卫和用户鉴权这里没太搞好,特别是在 Layout 组件里面(渲染用户可访问的菜单)。

现在我是这样做的

登录

用户登录后将用户的信息保存到 localStrorage 里面,其中保存了用户的基本信息,token ,及用户的可访问 menus 。然后跳转到主页

localStorage.setItem(KeyUser, JSON.stringify(data))
toast.success('success', {
   autoClose: successTime, onClose: () => {
       Router.push('/')
   }
})

_app.js

_app.js页面的基本布局这里会使用 Layout 组件进行用户可访问的菜单渲染。代码如下

import {Layout} from "../components/Layout";

function MyApp({Component, pageProps, router}) {
	...
    if (router.route === '/login') return <><Component {...pageProps} /></>
    return <ThemeProvider theme={theme}>
        <Layout dark={dark} setDark={handleSetDark} theme={theme}>
            <Component {...pageProps} />
        </Layout>
        <ToastContainer position={'top-center'} theme={'dark'}/>
    </ThemeProvider>
}

Layout.js

问题主要在这里,如果直接将 localStorage 的用户信息删除,由于useUser里没有判断到用户信息为空而跳转到login页面,所以继续向Layout组件里面走了。

这里的前两个 if 条件也不能阻止程序往下执行所以 {menus.map 里面回报 undefined.

(其实我有在 useUser 里面做判断,如果用户信息不存在直接到/login页面。但没有起效果)

export const Layout = ({children, dark, setDark, theme}) => {
    const {menus, u, mutate, loading, token, loggedOut} = useUser()
    if (loading) return <>{children}</>
    if (!u) return <></>
    ...
    return (<Box sx={{display: 'flex'}}>
    	<List>
        {menus.map(item)=> ...}
        </List>
        ...
        {childlren}
        ...
    </Box>);
}

useUser.js

这是useUser.js用来获取用户的信息,如果用户没有登录就直接跳到登录页面。

获取用户信息是从localStorage里面进行获取的,参照官网的 demo 中改来。

...
const userFetcher = async () => {
    let u = localStorage.getItem(KeyUser)
    if (isEmpty(u)) {
        let error = new Error("Not authorized!");
        error.status = 403
        throw error
    }
    return JSON.parse(u)
}
export const useUser = () => {
    const {data, mutate, error} = useSWR(`api_user`, userFetcher)
    const loggedOut = error && error.status === 403;
    const loading = loggedOut === undefined || !data && !error;
    if (loggedOut) {
        Router.push('/login')
    }
    if (data) {
        const {u, menus, token} = data.data
        return {loading, mutate, u, menus, token, loggedOut}
    }
    return {loading, loggedOut}
}

所以想请问一下大家这块如何做比较好呢?

刚学 react,nextjs 没多久,请多指教呀 ^_^。

2684 次点击
所在节点    问与答
6 条回复
adjusted
2022-01-03 11:30:32 +08:00
sciel
2022-01-03 11:37:56 +08:00
@adjusted 没有,一会去看看哈,谢谢。
walpurgis
2022-01-03 13:10:56 +08:00
服务端渲染的页面建议把用户登录态放到 cookie 里
jielong
2022-01-03 13:31:58 +08:00
用了 next 最好能做到服务端渲染阶段拿到用户信息,不然感觉会很奇怪 😅

推荐这两个库,用户信息,token 放 cookie ,能在 serverSide 拿到

https://github.com/bjoluc/next-redux-cookie-wrapper
https://github.com/kirill-konshin/next-redux-wrapper
sciel
2022-01-03 13:57:54 +08:00
@walpurgis
@jielong 之前试过服务端渲染,但后台给自己用的没必要,所以还是放客户端好做点。方便在 localStorage 里面取数据。 试过放 cookie 里,但 cookie 里面存的信息有限,用户 menus 放不下。
page470075640
2022-01-03 18:29:11 +08:00
我的做法是登入后的页面会去拉取用户信息 如果拿不到就重定向 login 页面

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/825879

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX