VUE中使用adal-angular, acquireToken刷新token的问题

寇宏义
2023-12-01

问题-----有没有大哥看看哪里有问题

报错

   renewal operation failed due to timeout

代码—(TS)

AuthService
import AuthenticationContext from "adal-angular";
export default class AuthService {
  private ctx: AuthenticationContext;
  private options: AuthenticationContext.Options;

  constructor(options: AuthenticationContext.Options) {
    this.options = options;
    this.ctx = new AuthenticationContext(options);

    new Promise((resolve, reject) => {                //   这里 有疑惑
      console.log("this.ctx", this.ctx);
      if (
        this.ctx.isCallback(window.location.hash) ||
        window.self !== window.top
      ) {
        // redirect to the location specified in the url params.
        this.ctx.handleWindowCallback();
      } else {
        // try pull the user out of local storage
        let user = this.ctx.getCachedUser();

        // if (user) {
        //   resolve();
        // }
        // else {
        //   // no user at all - go sign in.
        //   this.login();
        // }
      }
    });
  }

  get user() {
    return this.ctx.getCachedUser();
  }

  get accessToken() {
    return this.ctx.getCachedToken(this.options.clientId);
  }

  get isAuthenticated(): boolean {
    return !!this.user && !!this.accessToken;
  }

  get roles(): string[] {
    return (this.user ? this.user.profile.roles : []) || [];
  }

  login() {
    this.ctx.login();
  }

  logout() {
    this.ctx.logOut();
  }

  acquireToken(resource?: string): Promise<string> {
    this.ctx.handleWindowCallback();            //   不清楚  这边 要不要写
    resource = resource || this.options.clientId;
    return new Promise((resolve, reject) => {
      this.ctx.acquireToken(resource, (err, token) => {
        if (err) {
          reject(err);
          this.ctx.handleWindowCallback();      //   不清楚  这边 要不要写
        } else {
          this.ctx.handleWindowCallback();  //   不清楚  这边 要不要写
          resolve(token);
        }
      });
    });
  }

  acquireTokenPopup(resource?: string) {
    resource = resource || this.options.clientId;
    return new Promise((resolve, reject) => {
      this.ctx.acquireTokenPopup(resource, null, null, (err, token) => {
        if (err) {
          reject(err);
        } else {
          resolve(token);
        }
      });
    });
  }

  acquireTokenRedirect(resource?: string) {
    resource = resource || this.options.clientId;
    return new Promise((resolve, reject) => {
      this.ctx.acquireTokenPopup(resource, null, null, (err, token) => {
        if (err) {
          reject(err);
        } else {
          resolve(token);
        }
      });
    });
  }

  checkRoles(roles: string[] | string) {
    if (!this.isAuthenticated) {
      return false;
    }
    if (!this.roles) {
      return false;
    }
    if (typeof roles === "string") {
      roles = [roles];
    }

    let userRoles = this.roles.map(t => t.toLowerCase());
    for (let i = 0; i < roles.length; i++) {
      if (userRoles.includes(roles[i].toLowerCase())) {
        return true;
      }
    }
    return false;
  }
  
  isTokenExpired() {
    let expiredTime = this.user.profile.exp;
    let nowTime = new Date().getTime() / 1000;
    return expiredTime - nowTime < 5 * 60;
  }
}

auth.ts

let authService: AuthService = null;
let roles = RoleMapping.map(t => t.role);

namespace AAD {
  export interface Options {
    router: Router;
    config: AuthenticationContext.Options;
  }
}

export default {
  install(vue: VueConstructor<any>, options: AAD.Options) {
    if (!options || !options.router || !options.config) {
      throw new Error("options {router,config} is required");
    }

    options.config.callback = (errorDesc, token, error) => {
      console.log("token", token);
      let redirect = "/home";
      let route = options.router.currentRoute;
      if (route && route.query && route.query.redirect) {
        redirect = route.query.redirect.toString();
      }
      redirect = window.location.origin + "/#" + redirect;
      window.location.href = redirect;
    };
    authService = new AuthService(options.config);
    vue.prototype.$auth = authService;
    options.router.beforeEach((to, from, next) => {
    //,...
    }); //end beforeEach
  }
};

export { authService as auth };
base.ts
import state from "../store";
import axiosRequest from "@/utils/request";
import { URL } from "./constant";
import { AxiosRequestConfig } from "axios";
import { getMockData } from "@/mock"; // 不打包mock相关代码
import { auth } from "@/plugins/auth";
import { randomNum } from "@/utils";

declare global {
  interface Window {
    isRefreshing: boolean;
  }
}

window.isRefreshing = false;

/*被挂起的请求数组*/
let refreshSubscribers: any[] = [];

/*push所有请求到数组中*/
function subscribeTokenRefresh(cb: any) {
  refreshSubscribers.push(cb);
}

/*刷新请求(refreshSubscribers数组中的请求得到新的token之后会自执行,用新的token去请求数据)*/
function onRrefreshed(token: any) {
  refreshSubscribers.map(cb => cb(token));
}

function formatURL(url: string, params: any, remove: boolean = true) {
  for (const key in params) {
    if (new RegExp("({" + key + "})").test(url)) {
      url = url.replace(RegExp.$1, params[key].toString());
      if (remove) {
        delete params[key];
      }
    }
  }
  return url;
}

export async function request(options: AxiosRequestConfig): Promise<any> {
  options.baseURL = URL.baseURL;
  const isMock = state.getters.setting.mock === true;

  options.url = formatURL(options.url, options.params);
  options.headers = options.headers || {};
  options.headers["x-source"] = window.location.origin;
  let token = auth.accessToken;
  if (options.url == "/auth/v1/users/registry") {
    return axiosRequest(options);
  }
  options.headers.Authorization = `Bearer ${token}`;

  if (auth.isTokenExpired()) {
    if (!window.isRefreshing) {
      window.isRefreshing = true;
      let token = await auth
        .acquireToken()
        .then(res => {
          console.log("newToken", res, auth.accessToken);
          options.headers.Authorization = `Bearer ${res}`;
          if (auth.accessToken) {
            onRrefreshed(auth.accessToken);
            refreshSubscribers = [];
          }
        })
        .catch(err => {
          console.log("new error", err);
          return Promise.reject(err);
        })
        .finally(() => {
          setTimeout(() => {
            options.headers.Authorization = `Bearer ${auth.accessToken}`;
            console.log("new token");
            window.isRefreshing = false;
          }, 2000);
        });
    }
    let retry = new Promise((resolve, reject) => {
      subscribeTokenRefresh((token: any) => {
        options.headers.Authorization = "Bearer " + token;
        resolve(options);
      });
    });
    return retry;
  } else {
    let token2 = "";
    auth
      .acquireToken()
      .then(token => {
        token2 = token;
        console.log("get token", token);
      })
      .catch(err => console.log("get error", err));
    setTimeout(() => {
      console.log("token error each", { token, token2 }, token === token2);
    }, 2000);
    console.log("token222", token);

    return axiosRequest(options);
  }
}
 类似资料: