react登录路由控制

登录访问控制

  • AuthRoute 鉴权路由组件实现思路
  • 参照官网自己封装AuthRoute 鉴权路由组件
  • 实现修改登录成功后的跳转

概述

项目中的两种类型的功能和两种类型的页面:

两种功能:

  • 登录后才能进行操作(比如:获取个人资料)
  • 不需要登录就可以操作(比如:获取房屋列表)

两种页面:

  • 需要登录才能访问(比如:个人中心页)
  • 不需要登录即可访问(比如:首页)

对于需要登录才能操作的功能使用 axios 拦截器 进行处理(比如:统一添加请求头 authorization等)

对于需要登录才能访问的页面使用 路由控制

功能处理-使用axios拦截器统一处理token

  • 在api.js 中,添加请求拦截器 (API.interceptors.request.user())
  • 获取到当前请求的接口路径(url)
  • 判断接口路径,是否是以/user 开头,并且不是登录或注册接口(只给需要的接口添加请求头)
  • 如果是,就添加请求头Authorization
// 添加请求拦截器
API.interceptors.request.use(config => {
  const { url } = config
  // 判断请求url路径
  if (
    url.startsWith('/user') &&
    !url.startsWith('/user/login') &&
    !url.startsWith('/user/registered')
  ) {
    // 添加请求头
    config.headers.Authorization = getToken()
  }
  return config
})
  • 添加响应拦截器 (API.interceptors.response.use())
  • 判断返回值中的状态码
  • 如果是400,标示token超时或异常,直接移除token
// 添加响应拦截器
API.interceptors.response.use(response => {
  const { status } = response.data
  if (status === 400) {
    // 此时,说明 token 失效,直接移除 token 即可
    removeToken()
  }
  return response
})

页面处理-AuthRoute鉴权路由组件

实现原理

  • 限制某个页面只能在登陆的情况下访问,但是在React路由中并没有直接提供该组件,需要手动封装,来实现登陆访问控制(类似与Vue路由的导航守卫)

  • 参数 react-router-dom的鉴权文档

  • AuthRoute 组件实际上就是对原来Route组件做了一次包装,来实现一些额外的功能

    • 使用

  • render方法:render props模式,指定该路由要渲染的组件内容

  • Redirect组件:重定向组件,通过to属性,指定要跳转的路由信息

// 官网封装的核心逻辑代码
// ...rest  把之前的组件中传递的属性原封不动传递过来
function PrivateRoute({ component: Component, ...rest }) {
  return (
    <Route
      {...rest}
      // render方法: render props模式,指定该路由要渲染的组件内容
      render={props =>
        // 判断是否登陆,如果登陆,跳转配置的component,如果没有登陆,利用 Redirect组件来进行重定向
        fakeAuth.isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              // 把当前的页面路径保存起来,方便用户登录后能够跳回当前页面
              state: { from: props.location }
            }}
          />
        )
      }
    />
  );
}

封装AuthRoute鉴权路由组件

  • 在components目录中创建AuthRoute/index.js 文件
  • 创建组件AuthRoute并导出
  • 在AuthRoute组件中返回Route组件(在Route基础上做了一层包装,用于实现自定义功能)
  • 给Route组件,添加render方法,指定改组件要渲染的内容(类似与component属性)
  • 在render方法中,调用isAuth() 判断是否登陆
  • 如果登陆了,就渲染当前组件(通过参数component获取到要渲染的组件,需要重命名)
  • 如果没有登陆,就重定向到登陆页面,并且指定登陆成功后腰跳转的页面路径
  • 将AuthRoute组件接收到的props原样传递给Route组件(保证与Route组件使用方式相同)
  • 使用AuthRoute组件配置路由规则,验证是否实现页面的登陆访问控制
const AuthRoute = ({ component: Component, ...rest }) => {
  return (
    <Route
      {...rest}
      render={props => {
        const isLogin = isAuth()

        if (isLogin) {
          // 已登录
          // 将 props 传递给组件,组件中才能获取到路由相关信息
          return <Component {...props} />
        } else {
          // 未登录
          return (
            <Redirect
              to={{
                pathname: '/login',
                state: {
                  from: props.location
                }
              }}
            />
          )
        }
      }}
    />
  )
}
export default AuthRoute

修改登录成功跳转

  • 登陆成功后,判断是否需要跳转到用户想要访问的页面(判断props.location.state 是否有值)
  • 如果不需要,则直接调用history.go(-1) 返回上一页
  • 如果需要,就跳转到from.pathname 指定的页面(推荐使用replace方法模式,不是push)
 // 表单的提交事件
  handleSubmit: async (values, { props }) => {
    ...
    if (status === 200) {
      // 登录成功
      localStorage.setItem('hkzf_token', body.token)

      /* 
        1 登录成功后,判断是否需要跳转到用户想要访问的页面(判断 props.location.state 是否有值)。
        2 如果不需要(没有值),则直接调用 history.go(-1) 返回上一页。
        3 如果需要,就跳转到 from.pathname 指定的页面(推荐使用 replace 方法模式,而不是 push)。
      */
      if (!props.location.state) {
        // 此时,表示是直接进入到了该页面,直接调用 go(-1) 即可
        props.history.go(-1)
      } else {
        // replace: [home, map]
        props.history.replace(props.location.state.from.pathname)
      }
    } else {
      // 登录失败
      Toast.info(description, 2, null, false)
    }
  }
posted @ 2021-01-03 14:50  sk-xm  阅读(791)  评论(0编辑  收藏  举报