React Network request Interconnect login API

The front store

localstorage

The data stored by the localStorage method has no time limit

Storage mode:

It is permanently stored in key-value pairs and never loses validity unless manually deleted

Commonly used API:

GetItem // Obtain records

SetIten // Save the record

RemoveItem // Removes the record

Clear // Clear records

sessionstorage

HTML5 localStorage API localStorage and sessionStorage are used in the same way

The difference is that sessionStorage is cleared as soon as the page is closed, while localStorage is kept forever

Used in the project

To store the token
  • encapsulationlocalStorageAPI, exposed to provide operation methods

Utils.js adds several operation methods

/ / save
export const saveAccessToken = (token) = > {
  localStorage.setItem(MOOSE_REACT_LEARN_ACCESS_TOKEN, token);
};

/ / to get
export const getAccessToken = () = > {
  return localStorage.getItem(MOOSE_REACT_LEARN_ACCESS_TOKEN) || 'MOOSE_REACT_LEARN';
};

/ / remove
export const removeAccessToken = () = > {
  localStorage.removeItem(MOOSE_REACT_LEARN_ACCESS_TOKEN);
};

// Encapsulate the parameters in the request header
export const getAuthorization = () = > {
  let accessToken = getAccessToken();
  returnisEmpty(accessToken) ? {}, {Authorization: `Bearer ${getAccessToken()}`}; };// Redirect to the login interface for login
export const redirectLogin = () = > {
  const { redirect } = getPageQuery(); // Note: There may be security issues, please note
  if (window.location.pathname ! = ='/login' && !redirect) {
    removeAccessToken();
    history.replace({
      pathname: '/login'.search: stringify({
        redirect: window.location.href, }), }); }};Copy the code
  • After the login is complete, use thelocalStorageSave the AccessToken returned by the interface

Example Modify the login interface logic

import { saveAccessToken } from '@/utils/utils'; . *login({ payload }, { call, put }) {
// Submit the processed parameters
      const response = yield call(postAccountLogin, params);
      yield put({
        type: 'changeLoginStatus'.payload: response,
      }); // Login successfully
      if (response.code === 200) {

        // Add this line
        saveAccessToken(response.data);

        const urlParams = new URL(window.location.href); .Copy the code
  • Put accessToken in the request header and send it on every request

Modify request.js package, add umi-Request request interceptor

request.interceptors.request.use(
  (url, options) = > {
    // console.log('request.interceptors.request', options);
    // Some other properties can be set
    return {
      url,
      options: { ...options, headers: {... options.headers, ... getAuthorization() } }, }; }, {global: true});Copy the code

Modify SecurityLayout so that the userId is the same as the returned field

Modify AvatarDropdown,userName and return to the same field

The refresh token

OAuth2.0 password mode authorization, which returns access_token and refresh_token

The server interface only returns access_token after login, refresh_token is saved to the server (redis).

The expiration time of refresh_token should be set longer than that of access_token. Ensure that refresh_token can be used to request access_token

When the Access_Token is invalid, the front end requests refresh_token using the last Access_Token, returns the access_token, and requests again

reference

  • Spring Boot 2.x Quick Start
  • SpringBoot OAuth2.0 Authentication and authorization (password mode)
  • SpringBoot OAuth2.0 encapsulates the login and refresh token interface

The API return code needs to be agreed with the front end

  • Java service interface definitioncode
  /** * token */
  TOKEN_IS_EMPTY(-10101."token must not be null"),
  TOKEN_VALIDATE_FAIL(-10102."token check fail"),
  TOKEN_INVALID(-10103."invalid access token"),
  REFRESH_TOKEN_NOT_EXIST(-10104."refresh token not exist"),
  ACCESS_TOKEN_IS_EMPTY(-10105."access token is empty"),
Copy the code
  • Invoke the refresh token interfaceservices/token.js
import { getAccessToken } from '@/utils/utils';
import request from '@/utils/request';

export async function postRefreshToken() {
  return request('/api/v1/token/refresh', {
    method: 'POST'.requestType: 'form'.data: {
      accessToken: getAccessToken(),
    },
  });
}
Copy the code
  • Modify therequest.js
// Retry function
const retry = (response, options) = > {
  return request(response.url, options);
};

request.interceptors.response.use(async (response, options) => {
  // Copy the last request
  const { status } = await response.clone();
  if (status === 401) {
    const { code: normalCode } = await response.clone().json();
    if (normalCode === 401) {
      redirectLogin();
      return;
    }

    // -10103 indicates that the request token is invalid
    if (normalCode === -10103) {
      const { data, code: refreshCode } = await postRefreshToken();

      // Return code when the refresh token is obtained
      if (refreshCode === -10101 || refreshCode === -10102 || refreshCode === -10104) {
        redirectLogin();
        return;
      }
      saveAccessToken(data);
      returnretry(response, options); }}return response;
});
Copy the code

When the accessToken time expires, refreshToken can be used to obtain accessToken again to continue the request