单击 sso 按钮后,我想在成功验证用户身份后重定向到 /home 页面

问题描述 投票:0回答:1

我在 azure 中创建了一个 Web 应用程序,并尝试使用 MSAL React 库配置 sso。但是,当单击 sso 按钮时,它不会重定向到 /home 页面,而且令牌生成也不会发生。

Authconfig.js

export const msalConfig = {auth: {clientId: "client-id",authority: "\`\`https://login.microsoftonline.com/tenant-id\`\`",redirectUri: "\`\`http://localhost:5173/home\`\`",},cache: {cacheLocation: "sessionStorage",  issuesstoreAuthStateInCookie: false,},};

main.jsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import { PricingComponent } from './PricingComponent.jsx';

import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import { AboutComponent } from './AboutComponent.jsx';
import { AdminComponent } from './AdminComponent.jsx';
import { BuildComponent } from './BuildComponent.jsx';
import { ContactusComponent } from './ContactusComponent.jsx';
import { FeedbackComponent } from './FeedbackComponent.jsx';
import { LandingPageComponent } from './LandingPageComponent.jsx';
import { LoginPageComponent } from './LoginPageComponent.jsx';
import { ReleasenotesComponent } from './ReleasenotesComponent.jsx';
import { UserHomeComponent } from './UserHomeComponent.jsx';
import { UserProfileComponent } from './UserProfileComponent.jsx';
import './index.css';
import { ProtectedRoutes } from './utils/ProtectedRoutes.jsx';


const router = createBrowserRouter([
{
  path:'/',
  element: <LandingPageComponent />,
  
  errorElement: <div>404 not found</div>,
  children : [
    {
      path: '',
      element: <AboutComponent />,
    },
    {
      path: 'pricing',
      element: <PricingComponent />,
    },
    {
      path: 'releasenotes',
      element: <ReleasenotesComponent /> ,
    },
    
    {
      path: 'contactus',
      element: <ContactusComponent />,
    },
    {
      path: 'signin',
      element: <LoginPageComponent />,
    },
    {
    element: <ProtectedRoutes />,
    children: [
    {
      path: 'home',
      element: <UserHomeComponent />,
    },
    {
      path: 'build',
      element: <BuildComponent />,
    },
    {
      path: 'admin',
      element: <AdminComponent /> ,
    },
    {
      path: 'userprofile',
      element: <UserProfileComponent /> ,
    },
    {
      path: 'feedback',
      element: <FeedbackComponent />,
    },
    ],
    },
    
  ],
},


]);

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
   
    <RouterProvider router={router} />
    
  </React.StrictMode>,
)

登录页面组件.jsx


import React, { useContext } from "react";
import { useNavigate } from 'react-router-dom';
import loginimage from './assets/loginimage.svg';
import { useMsal } from "@azure/msal-react";
import { loginRequest } from './Authconfig';

export const LoginPageComponent = () => {
  const { instance } = useMsal();
  const handleLogin = () => {
    instance.loginRedirect(loginRequest);
    };


    
    return (
        <div className="bg-white">
            <div className="grid grid-cols-2 justify-center items-center m-20">
                <div>
                    <img
                        loading="lazy"
                        src={loginimage}
                        className="self-end max-w-full aspect-square w-[540px]"
                    />
                </div>
                <div className="flex flex-col ml-5">
                    <div className="flex flex-col p-10 mt-5 w-fit items-center justify-center rounded-lg shadow-sm bg-sky-600 bg-opacity-20 text-zinc-800 max-md:px-5 max-md:mt-10">
                        <div className="text-4xl font-black text-sky-600">      
                      </div>
                        <button
                            onClick={handleLogin}
                            className="w-96 px-8 py-3 ml-6 rounded-lg bg-indigo-500 text-gray-100 border border-gray-200 placeholder-gray-500 text-sm tracking-wide font-semibold hover:bg-indigo-700 transition-all duration-300 ease-in-out flex items-center justify-center focus:shadow-outline focus:outline-none mt-5"
                        >
                            <svg className="w-6 h-6 -ml-2" fill="none" stroke="currentColor">
                                <path d="M16 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
                                <circle cx="8.5" cy="7" r="4" />
                                <path d="M20 8v6M23 11h-6" />
                            </svg>
                            <span className="ml-3">Login With SSO</span>
                        </button>
                    </div>
                </div>
            </div>
        </div>
    );
}
UserHomeComponent.jsx
import React, { PureComponent, useContext, useEffect, useState } from 'react';
import { AiOutlineExclamationCircle } from "react-icons/ai";
import { CiCircleRemove } from "react-icons/ci";
import { FaRegCircleCheck } from "react-icons/fa6";
import { PiClockCountdown } from "react-icons/pi";
import { Area, AreaChart, Bar, BarChart, Cell, Label, Pie, PieChart, Rectangle, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
import bannerlogo from './assets/buildnowlogo.svg';
import { AuthContext } from './utils/AuthContext';

export const UserHomeComponent = () => {

  const [orgdata, setOrgData] = useState([]);
  const [responsedata,setResponsedata] = useState([]);
  const [responsedata2,setResponsedata2] = useState([]);
  const [responsedata3,setResponsedata3] = useState([]);
  const [changefailrate,setChangeFailRate] = useState([]);
  const [failurejobs,setFailurejobs] =useState([]);
  const [successjobs,setSuccessjobs] =useState([]);
  const [unstablejobs,setUnstablejobs] =useState([]);
  const [avgleadtime,setAvgleadtime] =useState([]);
  const [searchTerm, setSearchTerm] = useState('');
  const [queryDate, setQueryDate] = useState('30');
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);
  const {user} = useContext(AuthContext);
  const [postdata,setPostData] = useState({orgname: "", days: "" , projectbasename:""});
  const [ischange, setIsChange] = useState(false);
  const [visibleTooltip, setVisibleTooltip] = useState(null);
  const baseUrl = import.meta.env.VITE_REACT_APP_BACKEND_BASE_URL;
  const RADIAN = Math.PI / 180;
  const cx = 120;
  const cy = 100;
  const iR = 60;
  const oR = 100;
  const percentage = changefailrate.Percentage
  const color = '#d0d000';

  const isAdm = user.isServiceAdmin
  const userid=user.userinfo.sAMAccountName
  const memberrole=user.memberRoles
  
  
  const handleSelectionChange = (e) => {
  
    const [ofr, spr] = e.target.value.split(' ');
    setPostData({orgname:ofr,days:queryDate,projectbasename:spr});
    
    setIsChange(true);
    
    };


const fetchOrgData = async () => {

  const userdetail = {
    username: userid,
    isServiceAdmin: isAdm,
    memberRoles:memberrole
  };
    const response= await fetch(`${baseUrl}/buildNowJenkins/getMultiBranch`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(userdetail),
      });
    const result =await response.json();
    
    
      setOrgData(result);
      setPostData({orgname:result.multiBranchInfo[0].OrgFolder,days:queryDate,projectbasename:result.multiBranchInfo[0].MultiBranchProject});
      setIsChange(true);
  };



  const handledateChange  = (e) => {
    const dat = e.target.value;
    setQueryDate(dat);
    postdata.days = dat
    setIsChange(true);
    
  
  };


  const filteredList = (orgdata.multiBranchInfo || []).filter((item) =>
    `${item.OrgFolder} ${item.MultiBranchProject}`
      .toLowerCase()
      .includes(searchTerm.toLowerCase())
  );


useEffect(() => {
  
  fetchOrgData();

  }
, []);


    
const handleSearchChange = (e) => {
  setSearchTerm(e.target.value);

};

const fetchfailurejobs =async() => {
  setIsLoading(true);

  try {
    const response = await fetch(`${baseUrl}/buildNowAdm/buildnowdorametrics/projectfailurejobs/`,{
      method:'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(postdata),
    });
    const responsedata = await response.json();
    setFailurejobs(responsedata)
    
  } catch (error) {
    console.error('Error fetching data:', error);
  } finally{
    setIsLoading(false);
  } 
};

const fetchsuccessjobs =async() => {
  setIsLoading(true);
  try {
    const response = await fetch(`${baseUrl}/buildNowAdm/buildnowdorametrics/projectsuccessjobs/`,{
      method:'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(postdata),
    });
    const responsedata = await response.json();
    setSuccessjobs(responsedata)
    
  } catch (error) {
    console.error('Error fetching data:', error);
  } finally{
    setIsLoading(false);
  }
};

const fetchunstablejobs =async() => {
  setIsLoading(true);

  try {
    const response = await fetch(`${baseUrl}/buildNowAdm/buildnowdorametrics/projectunstablejobs/`,{
      method:'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(postdata),
    });
    const responsedata = await response.json();
    setUnstablejobs(responsedata)
    
  } catch (error) {
    console.error('Error fetching data:', error);
  } finally{
    setIsLoading(false);
  }
};

const fetchaverageleadtime =async() => {
  setIsLoading(true);

  try {
    const response = await fetch(`${baseUrl}/buildNowAdm/buildnowdorametrics/projectaverageleadtime/`,{
      method:'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(postdata),
    });
    const responsedata = await response.json();
    setAvgleadtime(responsedata)
    
  } catch (error) {
    console.error('Error fetching data:', error);
  } finally{
    setIsLoading(false);
  }
};


const projectleadtime = async () => {
  setIsLoading(true);
  
  try {
    const response = await fetch(`${baseUrl}/buildNowAdm/buildnowdorametrics/projectleadtime/`,{
      method:'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(postdata),
    });
  
    const responsedata = await response.json();
    setResponsedata2(responsedata)
    
  } catch (error) {
    console.error('Error fetching data:', error);
  } finally{
    setIsLoading(false);
  }
  
};

const projectdeploymentfrequencydaywise = async () => {
  setIsLoading(true);
  try {
    const response = await fetch(`${baseUrl}/buildNowAdm/buildnowdorametrics/projectdeploymentfrequencydaywise/`,{
      method:'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(postdata),
    });
  
    const responsedata = await response.json();
    setResponsedata(responsedata)
    
  } catch (error) {
    console.error('Error fetching data:', error);
    
  } finally{
    setIsLoading(false);
  }
  
};


const projectdeployment = async() => {
  setIsLoading(true);
  try {
    const response = await fetch(`${baseUrl}/buildNowAdm/buildnowdorametrics/projectdeployment/`,{
      method:'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(postdata),
    });
  
    const responsedata = await response.json();
    setResponsedata3(responsedata)
  
  } catch (error) {
    console.error('Error fetching data:', error);
  } finally{
    setIsLoading(false);
  }
};

const changefailurerate = async() => {
    
  try {
    const response = await fetch(`${baseUrl}/buildNowAdm/buildnowadminmetrcs/changefailurerate/`,{
      method:'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(postdata),
    });
  
    const rd = await response.json();
    setChangeFailRate(rd)
  
  } catch (error) {
    console.error('Error fetching data:', error);
  }
};

const LoadingComponent = () => {
  return (
    <div class="border w-96 h-44 border-gray-100 ">
    <div class="animate-pulse flex">
        <div class=" flex space-x-4 items-end relative ml-20">
        <div class="w-4 bg-slate-200 rounded h-16"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        <div class="w-4 bg-slate-200 rounded h-24"></div>
        <div class="w-4 bg-slate-200 rounded h-16"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        <div class="w-4 bg-slate-200 rounded h-20"></div>
        <div class="w-4 bg-slate-200 rounded h-8"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        <div class="w-4 bg-slate-200 rounded h-20"></div>
        <div class="w-4 bg-slate-200 rounded h-24"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        <div class="w-4 bg-slate-200 rounded h-36"></div>
        <div class="w-4 bg-slate-200 rounded h-20"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        <div class="w-4 bg-slate-200 rounded h-16"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        <div class="w-4 bg-slate-200 rounded h-24"></div>
        <div class="w-4 bg-slate-200 rounded h-16"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        <div class="w-4 bg-slate-200 rounded h-20"></div>
        <div class="w-4 bg-slate-200 rounded h-8"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        <div class="w-4 bg-slate-200 rounded h-20"></div>
        <div class="w-4 bg-slate-200 rounded h-24"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        <div class="w-4 bg-slate-200 rounded h-36"></div>
        <div class="w-4 bg-slate-200 rounded h-20"></div>
        <div class="w-4 bg-slate-200 rounded h-32"></div>
        </div>
      
    
    </div>
  </div>
  )
};


class CustomizedLabel extends PureComponent {
  render() {
    const { x, y, value } = this.props;

    return (
      <text x={x} y={y} dy={-4}  fontSize={10} textAnchor="middle">
        {value}
      </text>
    );
  }
}


const needle = (percentage, cx, cy, iR, oR, color) => {
  const ang = 180.0 * (1 - percentage / 100); // calculate angle based on percentage
  const length = (iR + 2 * oR) / 3;
  const sin = Math.sin(-RADIAN * ang);
  const cos = Math.cos(-RADIAN * ang);
  const r = 5;
  const x0 = cx + 5;
  const y0 = cy + 5;
  const xba = x0 + r * sin;
  const yba = y0 - r * cos;
  const xbb = x0 - r * sin;
  const ybb = y0 + r * cos;
  const xp = x0 + length * cos;
  const yp = y0 + length * sin;

  return [
    <circle key="circle" cx={x0} cy={y0} r={r} fill={color} stroke="none" />,
    <path key="path" d={`M${xba} ${yba}L${xbb} ${ybb} L${xp} ${yp} L${xba} ${yba}`} stroke="none" fill={color} />,
  ];
};

if (ischange===true)
  {
  console.log(postdata);
  changefailurerate();
  projectdeployment();
  fetchsuccessjobs();
  fetchfailurejobs();
  fetchunstablejobs();
  fetchaverageleadtime();
  projectleadtime();
  projectdeploymentfrequencydaywise();
  setIsChange(false);
  };


  return (
    <>
    {
      user.memberRoles.length === 0 ? (
        <div className=' grid justify-center items-center h-[90%]  bg-slate-100 '>
          <div className=' shadow-md p-10 bg-slate-200 m-20'>
          <div className='flex items-center justify-center mb-10'>
          <img src={bannerlogo} />
          <h5 className='text-6xl text-center font-extrabold text-sky-700 ml-5'>buildNow</h5>
          
          </div>
          <h5 className='text-3xl text-center  text-slate-400 mb-5'>oops!...</h5>  
          <p className='text-center text-slate-700 text-2xl font-normal'>
          Your <span className='font-bold'> projects haven't been </span> migrated yet or your <span className='font-bold'>users haven't been assigned to the</span> IdM2BCD <span className='font-bold'>role</span>. <br/>
          Contact the <span className='font-bold'>buildNow team</span> for assistance.
          </p>
          </div>
        </div> ) : (
    <>
    <div className="justify-center items-center text-center p-2 mt-5 w-full text-2xl font-bold leading-9 text-sky-600 rounded-xl border border-black border-solid bg-zinc-900 max-md:px-5 max-md:max-w-full">
        DORA+ METRICS
    </div>

    <div className="grid grid-flow-col text-sky-800 font-bold justify-center items-center gap-10 mt-2 p-1">
    <div>
      <input
        type="text"
        placeholder="Search Project..."
        value={searchTerm}
        onChange={handleSearchChange}
        className='w-96'
      />
      <div>
      <select className='w-96'onChange={handleSelectionChange} value={`${postdata.orgname} ${postdata.projectbasename}`} >
      
        {filteredList.map((item) => (
          <option key={item.MultiBranchProject} value={`${item.OrgFolder} ${item.MultiBranchProject}`}>
            {item.OrgFolder} {item.MultiBranchProject}
          </option>
        
        ))}
      
      </select>
      </div>
      </div>

      <div>
      <select  size={1} defaultValue="30" onChange={handledateChange} value={postdata.days}
      className="block w-80 p-3 mt-1  border-b-2 border-gray-400 rounded-sm shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
        <option  value="7" id="daysDropdown">7 days</option>
        <option  value="14" id="daysDropdown">14 days</option>
        <option  value="30" id="daysDropdown">30 days</option>

      </select>
      </div>
      </div>
      <div className=' text-center'>
      {postdata.orgname && postdata.projectbasename && (
        <div >
          <p><span className=' font-semibold ' >Org:</span>  {postdata.orgname},  <span className=' font-semibold' > Project:</span> {postdata.projectbasename}</p>
      </div>
      )}
      </div>

      <div className=' grid grid-cols-12'>
      <div className='col-span-4 sm:gap-2 gap-4 mt-5 justify-center ml-5'>
      <div className=' flex flex-grow gap-2 md:gap-4 '>
      <div className="items-center justify-center bg-gray-50 rounded-xl shadow-sm mb-2">
      <div className='flex flex-auto items-center justify-center'>
      <h5 className="text-lg font-semibold text-gray-900 pe-1">Change Failure Rate</h5> 
      <div className='relative flex items'>
      <AiOutlineExclamationCircle
      size={10}
      onMouseEnter={() => setVisibleTooltip('1')}
      onMouseLeave={() => setVisibleTooltip(null)}
      className="cursor-pointer " />
      {visibleTooltip === '1' && (
        <div className="absolute bottom-full mb-2 w-96 p-2 bg-slate-50 text-sm rounded-md shadow-lg">
          Change failure rate represents the percentage of deployments that result in failures in the production environment. 
  
        </div>
      )}</div>
      </div>
      <div className='w-64 h-32' >
      <ResponsiveContainer >
      <PieChart >
        <Pie
          dataKey="value"
          startAngle={180}
          endAngle={0}
          data={[{ value: 100, color: '#ff1a1a' }]} // single slice to fill the semi-circle
          cx={cx}
          cy={cy}
          innerRadius={iR}
          outerRadius={oR}
          fill="#8884d8"
          stroke="none"
        >
        <Label value={`${percentage}%`}/>
        <Cell fill="#ff4d4d" /> {/* background color */}
        </Pie>
        {needle(percentage, cx, cy, iR, oR, color)}
        
      </PieChart>
      </ResponsiveContainer>
      </div>
      </div>
      <div className="grid justify-center w-40 h-40  bg-slate-50  rounded-xl shadow-sm ">
      <div className="flex flex-col items-center pb-10 mt-2">
      <div className='flex flex-auto justify-center'>
      <p className="mb-5 text-sm font-semibold font-sans pe-1">Overall Deployment</p>
      <div className='relative flex mt-1'>
      <AiOutlineExclamationCircle
      size={10}
      onMouseEnter={() => setVisibleTooltip('2')}
      onMouseLeave={() => setVisibleTooltip(null)}
      className="cursor-pointer" />
      {visibleTooltip === '2' && (
        <div className="absolute bottom-full mb-2 w-96 p-2 bg-slate-50 text-sm rounded-md shadow-lg">
          The total number of deployments carried out during the given time frame.
        </div>
      )}</div>
      </div>
      <h5 className="mt-3 text-4xl font-medium text-gray-900">{responsedata3.count}</h5>
      <PiClockCountdown  size={50} color="blue" />
      </div>
      </div>
      </div>
      <div className='flex flex-auto gap-2 md:gap-4 ml-2 mb-5 md:mt-5 lg:mt-10'>
      <div className="grid justify-center w-40 h-40  bg-slate-50  rounded-xl shadow-sm  ">
      <div className="flex flex-col items-center pb-10 mt-5">
      <div className='flex flex-auto justify-center'>
      <p className="mb-2 text-md font-semibold font-sans pe-1 ">Success Jobs</p>
      <div className='relative flex mt-1'>
      <AiOutlineExclamationCircle
      size={10}
      onMouseEnter={() => setVisibleTooltip('3')}
      onMouseLeave={() => setVisibleTooltip(null)}
      className="cursor-pointer" />
      {visibleTooltip === '3' && (
        <div className="absolute bottom-full mb-2 w-96 p-2 bg-slate-50 text-sm rounded-md shadow-lg">
          The total number of builds that were completed successfully during the specified time period.
        </div>
      )}</div>
      </div>
      <h5 className="mb-2 text-4xl font-medium text-gray-900">{successjobs.count}</h5>
      <FaRegCircleCheck   size={50} color="#00b300" />
      </div>
      </div>
      <div className="grid justify-center w-40 h-40  bg-slate-50   rounded-xl shadow-sm  ">
      <div className="flex flex-col items-center pb-10 mt-5">
      <div className='flex flex-auto justify-center'>
      <p className="mb-2 text-md font-semibold font-sans pe-1">Failure Jobs</p>
      <div className='relative flex mt-1'>
      <AiOutlineExclamationCircle
      size={10}
      onMouseEnter={() => setVisibleTooltip('4')}
      onMouseLeave={() => setVisibleTooltip(null)}
      className="cursor-pointer" />
      {visibleTooltip === '4' && (
        <div className="absolute left-full mb-2 w-96 p-2 bg-slate-50 text-sm rounded-md shadow-lg">
          The total number of builds that failed during the specified time period
        </div>
      )}</div>
      </div>
      <h5 className="mb-2 text-4xl font-medium text-gray-900">{failurejobs.count}</h5>
      <CiCircleRemove  size={50} color="#ff4d4d" />
      </div>
      </div>
      <div className="grid justify-center w-40 h-40 bg-slate-50  rounded-xl shadow-sm ">
      <div className="flex flex-col items-center pb-10 mt-5">
      <div className='flex flex-auto justify-center'>
      <p className="mb-2 text-md font-semibold font-sans pe-1">Unstable Jobs</p>
      <div className='relative flex mt-1'>
      <AiOutlineExclamationCircle
      size={10}
      onMouseEnter={() => setVisibleTooltip('5')}
      onMouseLeave={() => setVisibleTooltip(null)}
      className="cursor-pointer" />
      {visibleTooltip === '5' && (
        <div className="absolute left-full mb-2 w-64 p-2 bg-slate-50 text-sm rounded-md shadow-lg">
          The total number of Unstable builds carried out during the given time frame.
        </div>
      )}</div>
      </div>
      <h5 className="mb-2 text-4xl font-medium text-gray-900">{unstablejobs.count}</h5>
      <AiOutlineExclamationCircle  size={50} color="#ff8000" />
      </div>
      </div>
      </div>
      </div>

    
      <div className="col-span-8 mt-5 gap-4 m-2 justify-center ">
      <div className=" items-center justify-center bg-gray-50  rounded-xl shadow-sm mb-1 md:mb-5 lg:mb-15 ">
      <div class="flex justify-between items-center">
        { avgleadtime.AverageLeadTime && (
        <div class="text-left text-xs">
            Avg Lead Time<span className='text-2xl font-medium'>({avgleadtime.AverageLeadTime})</span>
        </div>)}
        <div class="mx-auto text-xl font-semibold relative flex">
        Lead Time
        <AiOutlineExclamationCircle
        size={10}
        onMouseEnter={() => setVisibleTooltip('6')}
        onMouseLeave={() => setVisibleTooltip(null)}
        className="  cursor-pointer ml-1 mt-2" />
        {visibleTooltip === '6' && (
          <div className="absolute bottom-full mb-2 w-96 p-2 bg-slate-50 text-sm font-normal rounded-md shadow-lg">
            Lead time for changes is the amount of time it takes a code change to get into production.
            This metric enables businesses to quantify the speed of code delivery to customers or stakeholders.
          </div>
          )}
        </div>
        </div>
      
        {isLoading ? <LoadingComponent /> : responsedata.length === 0 ? (
        <div className="h-44 text-center items-center justify-center pt-10 text-gray-300 font-extrabold text-2xl">Metrics not available for selected time period</div>
        ) : (
        <div className='w-full h-full'>
        <ResponsiveContainer width="100%" height={200}>
        <BarChart
        data={responsedata2}
          margin={{
            top: 5,
            right: 30,
            left: 20,
            bottom: 5,
          }}
        >
          <XAxis dataKey="time">
            <Label value="Date" offset={-5} position="insideBottom" />
            </XAxis>
          <YAxis>
          <Label value="Lead Time(mins)"  angle={-90} position="insideLeft" style={{ textAnchor: 'middle' }}  />
          </YAxis>
          <Tooltip dataKey="time" />
          
          <Bar dataKey="last" fill="#3366ff" activeBar={<Rectangle fill="purple"   />} />
        </BarChart>
      </ResponsiveContainer>
      
      </div>)
      }
      </div>
    
      <div className="  items-center justify-center  bg-gray-50  rounded-xl shadow-sm ">
      <div className='flex flex-auto justify-center'> 
      <h5 className="text-xl font-semibold leading-none text-center justify-center text-gray-900 pe-1">Deployment Frequency Day Wise</h5>
      <div className='relative flex mt-1'>
      <AiOutlineExclamationCircle
        size={10}
        onMouseEnter={() => setVisibleTooltip('7')}
        onMouseLeave={() => setVisibleTooltip(null)}
        className="  cursor-pointer" />
        {visibleTooltip === '7' && (
          <div className="absolute bottom-full mb-2 w-96 p-2 bg-slate-50 text-sm rounded-md shadow-lg">
            Day wise deployments carried out during the given time frame
          </div>
          )}</div>
          </div>
      {isLoading ? (<LoadingComponent />) : responsedata.length === 0 ? (
      <div className="h-44 text-center items-center justify-center pt-20 text-gray-300 font-extrabold text-2xl">Metrics not available for selected time period</div>
      ) : (
      <div>
      <ResponsiveContainer width="100%" height={200}>
        <AreaChart
        data={responsedata}
          margin={{
            top: 5,
            right: 30,
            left: 20,
            bottom: 5,
          }}
        >
          <XAxis dataKey = "time" >
            <Label value="Date" offset={-5} position="insideBottom"  />
          </XAxis>
          <YAxis>
          <Label value="count"  angle={-90} position="insideLeft" style={{ textAnchor: 'middle' }}  />
          </YAxis>
          <Tooltip />
          
          <Area  dataKey="count" fill="#0040ff"   activeDot={{ r: 3 }}  />
        </AreaChart>
      </ResponsiveContainer>
      </div>)
      }
      </div>
      </div>
      </div>
      </>
      ) 
    }
    </>
  )
}

AuthContext.jsx

import React, { useState } from 'react';

const AuthContext = React.createContext();

const AuthProvider = ({ children }) => {
    const [user, setUser] = useState(() => {
        const storedUser = localStorage.getItem('user');
        return storedUser ? JSON.parse(storedUser) : null;
    });

    const login = (userData) => {
        setUser(userData);
        localStorage.setItem('user', JSON.stringify(userData));
    };

    const logout = () => {
        setUser(null);
        localStorage.removeItem('user');
    };

    return (
        <AuthContext.Provider value={{ user,setUser,login,logout }}>
            {children}
        </AuthContext.Provider>
    );
};

export { AuthContext, AuthProvider };

ProtectedRoutes.jsx


import React, { useContext } from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import { AuthContext } from './AuthContext';

export const ProtectedRoutes = () => {
    const { account } = useContext(AuthContext);

    return account ? <Outlet/> : <Navigate to="/signin" />;
};

登陆页面组件.jsx

import React from 'react';
import { Outlet } from 'react-router-dom';
import { Header } from './Header';
import { AuthProvider } from './utils/AuthContext';

export const LandingPageComponent = () => {
  return (
    <>
     
    <AuthProvider>
    <Header />
    <Outlet />
    </AuthProvider>
    
    </>
    
  )
}

单击 SSO 按钮后,需要验证用户并需要重定向到 Userhomecomponent.jsx 页面。

我已将

http://localhost:5173/home
配置为 azure 中的redirectUri。我还添加了范围 openid、电子邮件和个人资料。我还启用了访问令牌和 id 令牌

reactjs azure single-sign-on msal
1个回答
0
投票

您可以使用 Uri 最佳实践来正确验证并重定向到 UserHomeComponent.jsx,文档建议您可以对重定向 Uri 使用 HTTPS 和 HTTP 架构。

注意:HTTP:HTTP 方案 (http://) 仅支持 localhost URI,并且仅应在活动的本地应用程序开发和测试期间使用。

该注释表明您的架构部分正确http://localhost:5173/home,因此,如果您使用的是 Windows,请尝试添加指向 localhost 的 IPv4(我们假设您的应用程序正在运行到 Web 或模拟器中)同一台机器),尝试获取与本地主机等效的 IPv4,这样生产服务器/开发服务器将正确重定向到 UserHome 组件。

通常,您可以使用 ipconfig 命令或类似命令来获取它,

更多信息请访问:https://learn.microsoft.com/en-us/entra/identity-platform/reply-url#prefer-127001-over-localhost

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.