Skip to content

配置统一免登录页面

2023 年 12 月 22 日

场景

目前星充平台上的对每个页面都做了登录校验,如果没有登录,那么就会直接跳转到登录页面。

但是,我们会存在一些场景:我们对这些页面不需要进行权限校验,不需要登录限制。

思路

  1. 我们可以在入口文件(**app.js****)**里面进行判断
typescript
/**
 * 统一登录,如果使用三方接口方式登录,需要改写改方法
 * @param oldRender
 */
export async function render(oldRender: any) {
  const loginRes = await ssoGetUserInfo().catch((error) => {
    if (error.code === "E00005") {
      ssoRedirectFunction();
    }
  });
  oldRender(); 
}

目前就是上面代码的情况,一旦发现没有登陆,那么就会调用ssoRedirectFunction()这个函数

所以我们可以在判断之前加一个window.location.pathname来判断当前前缀(/noNeedToLogin)是否需要

关于oldRender()我的理解是:应用程序的渲染函数,用于将应用程序的组件渲染到页面上。

typescript
/**
 * 统一登录,如果使用三方接口方式登录,需要改写改方法
 * @param oldRender
 */
export async function render(oldRender: any) {
  // 如果页面是以/noNeedToLogin的时候,那么不需要登录
  if (window.location.pathname === "/noNeedToLogin") {
    return;
  }

  const loginRes = await ssoGetUserInfo().catch((error) => {
    if (error.code === "E00005") {
      ssoRedirectFunction();
    }
  });

  if (loginRes) {
    setStorage("M-USER", JSON.stringify((loginRes as any).model));
    getUserPower({
      userId: (loginRes as any).model.userId,
    }).then((res) => {
      // "M-POWER"; "M-RULES";
      // const rules = res.model.map((item: { code: string; }) => item.code);
      // sessionStorage.setItem("power", JSON.stringify(res.model || []));
      // sessionStorage.setItem("rules", JSON.stringify(rules || []));
      // setLoginChecked(true);
      console.log("res", res);
    });

    oldRender();
  }
}
  1. 封装,为了后续更好的管理,最好写一个专门的layout用于判断,是否需要登录校验

checked状态,用于判断是否进行了登录判断

- 如果登录状态为`false`,那么会返回`null`,也就是,子组件无法渲染出来
- 如果登录状态为`true`,那么就会渲染出相应的`children`
typescript
import { useLocation } from "umi";
import type React from "react";
import { useEffect, useState } from "react";
import { setStorage } from "@/utils/utils";
import { ssoGetUserInfo, ssoRedirectFunction } from "xxxxxx";
import { getUserPower } from "@/services/login";

/**
 * 不用登陆的Layout页面
 * @param param 
 * @returns 
 */
const SecurityLayout: React.FC<{ children: React.ReactNode; }> = ({ children }) => {
  const location = useLocation();
  const [loginChecked, setLoginChecked] = useState(false);

  useEffect(() => {
    if (!(location.pathname.startsWith("/notNeedToLogin"))) {
      ssoGetUserInfo()
        .then((loginRes: unknown) => {
          setStorage("userInfo", JSON.stringify(loginRes.model));
          getUserPower({
            userId: loginRes.model.userId,
          })
            .then((res) => {
              const rules = res.model.map((item: { code: string; }) => item.code);
              sessionStorage.setItem("power", JSON.stringify(res.model || []));
              sessionStorage.setItem("rules", JSON.stringify(rules || []));
              setLoginChecked(true);
            });
        })
        .catch((error) => {
          if (error.code === "E00005") {
            ssoRedirectFunction();
          }
        });
    } else {
      setLoginChecked(true);
    }
  }, [location.pathname]);

  if (!loginChecked) {
    return null;
  }
  return children;
};

export default SecurityLayout;

上述一些引用库简单描述:

  • setStorage:封装的方法,主要就是用于将数据存在storage里面
  • ssoGetUserInfossoRedirectFunction:内部组件库,用于sso单点登录
  • getUserPower:用于权限控制,获取用户的权限

那么在原先处理的地方,就不需要任何的处理,也就是在入口文件的render里面,不在需要登录的判断,后面的security页面会进行判断的。

typescript
export async function render(oldRender) {
  oldRender(); // 这个render函数中,就不需要写
}

那么我们在配置路由的时候,就要先走SecurityLayout这个页面

typescript
{
  path: "/",
    component: "../layouts/SecurityLayout",
    routes: [
    {
      path: "./notNeedToLogin",
      component: "../layouts/SecurityLayout",
      routes: [
        {
          path: "./threeCodeBindApp",
          name: "三码绑定APP",
          component: "../layouts/BlankLayout",
          routes: [
            {
              path: "./home",
              name: "三码绑定APP首页",
              component: "/src/pages/SupplyPlan/ThreeCodeBindApp",
            },
          ],
        },
      ],
    },
    {
      path: "./",
      component: "../layouts/BlankLayout",
      routes: [
        {
          path: "./",
          component: "../layouts/BasicLayout",
          routes: [
            {
              name: "主数据",
              icon: "money-collect",
              key: "MainData",
              routes: [
                {
                  path: "/bom",
                  key: "Bom",
                  name: "BOM",
                },
              ],
            },
          ],
        },
      ],
    },
  ]
}];