繁体   English   中英

React 中 next.js 中基于角色的路由

[英]Role based routes in next.js in React

我对 React 很陌生,我有一个入门套件,其中包含用于在 React 中进行身份验证的 next.js。 当用户访问管理员路由时,我想限制对它们的访问。

我有两个角色, adminuser ,它们在成功登录后存储在会话中。

_app.jsx inside pages 文件夹如下所示。

    /**
 * Custom Next.js App
 *
 * @see https://nextjs.org/docs#custom-app
 */

import React from 'react'
import Head from 'next/head'
import { NextAuth } from 'next-auth/client'
import withRedux from 'next-redux-wrapper'
import NextSeo from 'next-seo'
import App, { Container as NextContainer } from 'next/app'
import { Provider as ReduxProvider } from 'react-redux'
import { Favicon, GTMScript, WebFonts } from '../components/head'
import { AuthUserProvider } from '../contexts/AuthUserContext'
import makeSEO from '../lib/seo'
import makeStore from '../lib/store'
// Global CSS from SCSS (compiles to style.css in _document)
import '../styles/globals.scss'

class CustomApp extends App {
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {}

    ctx.session = await NextAuth.init({ req: ctx.req })

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }

    return {
      pageProps,
      seo: makeSEO(ctx.req),
      session: ctx.session,
    }
  }

  componentDidMount() {
    // picturefill for <picture> and srcset support in older browsers
    // eslint-disable-next-line global-require
    if (process.browser) require('picturefill')
  }

  render() {
    const { Component, pageProps, seo, session, store } = this.props

    return (
      <NextContainer>
        {
          // to keep <Head/> items de-duped we should use next/head in _app.jsx
          // @see https://github.com/zeit/next.js/issues/6919
        }
        <Head>
          <meta
            name="viewport"
            content="width=device-width, initial-scale=1, minimal-ui"
          />
          <WebFonts />
          <Favicon />
          <GTMScript />
        </Head>
        <ReduxProvider store={store}>
          <AuthUserProvider session={session}>
            <NextSeo config={seo} />
            <Component {...pageProps} />
          </AuthUserProvider>
        </ReduxProvider>
      </NextContainer>
    )
  }
}

export default withRedux(makeStore)(CustomApp)

任何人都可以指导我如何根据角色访问路线吗?

我能够获得使用 next-auth 和useSession 的角色。 希望这对您也有帮助。

模型/index.js

import User, { UserSchema } from "./User"

export default {
  User: {
    model: User,
    schema: UserSchema
  }
}

模型/User.js

import Adapters from "next-auth/adapters"

// Extend the built-in models using class inheritance
export default class User extends Adapters.TypeORM.Models.User.model {
  constructor(name, email, image, emailVerified, roles) {
    super(name, email, image, emailVerified)
    if (roles) { this.roles = roles}
  }
}

export const UserSchema = {
  name: "User",
  target: User,
  columns: {
    ...Adapters.TypeORM.Models.User.schema.columns,
    roles: {
      type: "varchar",
      nullable: true
    },
  },
}

页面/api/auth/[...nextauth].js

import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
import Adapters from 'next-auth/adapters'

import Models from '../../../models'

export default NextAuth({
  // @link https://next-auth.js.org/configuration/providers
  providers: [
    Providers.Google({
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET
    })
  ],
  // @link https://next-auth.js.org/tutorials/typeorm-custom-models
  adapter: Adapters.TypeORM.Adapter(
    process.env.DATABASE_URL,
    {
      models: {
        User: Models.User
      }
    }
  ),
  session: { jwt: true },
  callbacks: {
    async jwt(token, user, account, profile, isNewUser) {
      if (account?.accessToken) {
        token.accessToken = account.accessToken
      }
      if (user?.roles) {
        token.roles = user.roles
      }
      return token
    },
    async session(session, token) {
      if(token?.accessToken) {
        session.accessToken = token.accessToken
      }
      if (token?.roles) {
        session.user.roles = token.roles
      }
      return session
    }
  }
});

用法 - 在 JSX 中

{!session &&  sessionLoading && <p>Loading...</p>}
{!session && !sessionLoading && <p>Access Denied - Not logged in</p> }
{ session && !sessionLoading && !session.user?.roles?.includes("Verified") && <p>Access Denied - Unverified</p> }
{ session && !sessionLoading && session.user?.roles?.includes("Verified") && <>
  <p>Stuff for verified users</p>
  {session.user.roles && session.user.roles.includes("Admin") && <>
    <button id="doSomething">Admin Only</button>
  </>}
  <p>More stuff for verified users</p>
</>}

Github 线程

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM