React+TS utilise l'authentification pour le contrôle d'accès à la connexion (terminal mobile)

avant-propos

Besoins couramment rencontrés côté PC :

  1. Pages accessibles sans connexion, telles que les pages de connexion, 404 pages
  2. Uniquement connecté, pages accessibles avec un jeton, telles que des informations personnelles (uniquement connecté. Vous pouvez accéder aux pages)

Par conséquent, nous devons utiliser l'authentification pour le contrôle d'accès à la connexion dans le projet, et nous ne pouvons y accéder qu'après avoir obtenu le jeton. Si nous ne nous connectons pas, nous pouvons y accéder et laisser la page sauter à la page de connexion pour vous connecter .

Cela peut être réalisé en utilisant des gardes de routage en vue, mais il n'y a pas de garde de navigation dans React, ce qui nous oblige à l'encapsuler nous-mêmes

Alors comment y parvenir ?

Analysez d'abord, quelle que soit la page à laquelle ils sont accessibles par routage, afin que nous puissions commencer par le routage et encapsuler les composants pour déterminer s'il faut se connecter

Lorsque vous vous connectez, vous verrez la page que vous souhaitez visiter

Accéder à la page de connexion sans se connecter, laisser l'utilisateur se connecter

Un exemple d'authentification est fourni dans react-router-dom

image.pngAlors, comment encapsuler votre propre composant d'authentification dans React+TS ?

React+TS encapsule ses propres composants d'authentification

Étapes de mise en œuvre :

  1. Définissez les composants de routage privés. Créer un composant de routage PrivateRoute dans le répertoire des composants : implémenter une logique de contrôle d'accès de connexion pour le routage

    • Avec jeton, accès normal
    • Sans le jeton, redirigez vers la page de connexion et passez l'adresse de la route à accéder
  2. Utiliser des composants de routage

    1. Pages nécessitant une autorisation d'accès, utilisez des composants de routage privés

Analyse des composants de routage d'authentification PrivateRoute

  • Scénario : Restreindre l'accès à une page uniquement lorsque vous êtes connecté.

  • Remarque : Ce composant n'est pas directement fourni dans le routage React et doit être encapsulé manuellement pour implémenter le contrôle d'accès à la connexion (similaire à la protection de navigation du routage Vue).

  • Comment encapsuler ? Reportez-vous à l'exemple d'authentification fourni dans la documentation de react-router-dom.

  • comment utiliser? Utilisez le composant PrivateRoute au lieu du composant Route par défaut pour configurer les règles de routage.

  • Le composant PrivateRoute encapsule en fait le composant Route d'origine pour implémenter des fonctions supplémentaires.

  • <Route path component render>La méthode render, qui spécifie le contenu du composant à rendre pour cette route (similaire à la propriété component).

  • Composant de redirection : le composant de redirection, via l'attribut to, spécifie les informations de routage vers lesquelles accéder.

  • attribut state : indique que des informations supplémentaires sont attachées à la route. Ici, il est utilisé pour spécifier l'adresse de la page à saisir après une connexion réussie.

Comment utiliser:

   <PrivateRoute path="/xxx/xxx">
            <ProfileEdit />  // 登录之后才能访问的页面
   </PrivateRoute>
复制代码

Étapes de mise en œuvre :

Gestion des jetons

    // 用来对{token: string, refresh_token: string }做本地持久化

    import { Token } from '@/types/data'

    const TOKEN_KEY = 'geek-app'

    // 获取 token
    export function getToken (): Token {
      // 字符串转对象
      return JSON.parse(localStorage.getItem(TOKEN_KEY) || '{}')
    }

    // 设置 token
    export function setToken (data: Token): void {
      // 对象转字符串
      localStorage.setItem(TOKEN_KEY, JSON.stringify(data))
    }

    // 移除 token
    export function removeToken (): void {
      localStorage.removeItem(TOKEN_KEY)
    }

    // 判断是否登录(授权)
    export function hasToken (): boolean {
      return !!getToken().token
    }
复制代码

Jugement d'autorisation (encapsule PrivateRoute)

import { hasToken } from '@/utils/storage'
import { Route, Redirect, RouteProps } from 'react-router-dom'
// RouteProps 特有的类型
export const PrivateRoute = ({ children, ...rest }: RouteProps) => {
  return (
    <Route
      {...rest}
      render={props => {
        if (hasToken()) {
          return children
        }

        return (
          <Redirect
            to={{
              pathname: '/login',
              state: {
                from: props.location.pathname // 回跳地址
              }
            }}
          />
        )
      }}
    />
  )
}
复制代码

Utiliser PrivateRoute

dans App.tsx

      <PrivateRoute path="/profile/edit">
        <ProfileEdit />
      </PrivateRoute>
复制代码

Connexion traitée avec succès

import { useHistory, useLocation } from 'react-router-dom'
import { useDispatch } from 'react-redux'
import { Button, NavBar, Form, Input, List, Toast } from 'antd-mobile'

const dispatch = useDispatch()
//  登录收集信息
  const onFinish = async (values:loginForm) => {
    // console.log(values)
    try {
      await dispatch(getToken(values))
      // 轻提示
      Toast.show({
        icon: 'success',
        content: '登录成功',
        // 在关闭之后调用
        afterClose: () => {
        // location.state?.from 回跳
          const path = location.state?.from || '/'
          history.replace(path)
        }
      })
    } catch (e) {
      const err = e as AxiosError<{message:string}>
      const content = err.response?.data.message || '登录失败'
      Toast.show({
        icon: 'fail',
        content
      })
    }
  }
复制代码

encapsuler l'histoire

import { createBrowserHistory } from 'history'

const history = createBrowserHistory()

export default history
复制代码

Modification App.tsx

import history from '@/utils/history'

<Router history={history}><Router>
复制代码

Modifier l'interception de la réponse

Gestion du statut 401

  // 添加响应拦截器
instance.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么
    return response
  },
  async function (error) {
    // 对响应错误做点什么
    const er = error as AxiosError
    if (!er.response) {
      Toast.show({ content: '网络异常' })
      return Promise.reject(error)
    }
    if (er.response?.status === 401) {
      console.log(401)
      const { refresh_token } = getToken()
      // 没有 refresh_token 的情况
      if (!refresh_token) {
        Toast.show({ content: '请重新登录' })
        // 跳到登录页
        history.push({
          pathname: '/login',
          state: { from: history.location.pathname }
        })
        return Promise.reject(error)
      }
      try {
        const res = await axios.put(baseURL + 'authorizations', null, {
          headers: {
            Authorization: `Bearer ${refresh_token}`
          }
        })
        console.log(res)
        const newToken = { token: res.data.data.token, refresh_token }
        setToken(newToken)
        store.dispatch({
          type: 'login/token',
          payload: newToken
        })
        return instance(er.config)
      } catch (error) {
        Toast.show({ content: '请重新登录' })
        // 跳到登录页
        history.push({
          pathname: '/login',
          state: { from: history.location.pathname }
        })
        return Promise.reject(error)
      }
    }

    return Promise.reject(error)
  }
)
复制代码

Je suppose que tu aimes

Origine juejin.im/post/7083481223384793096
conseillé
Classement