为什么 Angular Guards canActivate 方法总是返回 false?

2024-01-03

我在登录后对用户进行基本身份验证,但发生了奇怪的行为,canActivate 返回 false,即使它是在正确的时间调用的。

in 登录组件

private login() {
  this.authService.login(this.loginForm.valid)
  .subscribe((data: any) => { // no need for pipe and map
    console.log("First");
    this.router.navigate(['/app']);
  })
}

in 认证服务:

login({ username, password }: any): Observable<any>{
    this.clearData();

    const loginData = {
      'username': username,
      'password': password
    };

    return this.http.post(environment['baseURL'] + '/api/auth/login', loginData).pipe(
      map(
        (data: any) => {
          if (data['token'] && data['user']) {
            this.isLoggedIn.next(true); 
            this.token = data['token'];
            localStorage.setItem('token', this.token);
            localStorage.setItem('usermeta', JSON.stringify(this.userData));
            return true;
          } else {
            return false;
          }
        },
        (error: any)=>{
          return of(false)
        }
      )
      
    )
  }

  getToken(): string {
    return this.token;
  }

  hasToken() {
    return this.getToken() ? true : false;
  }

in auth.guard.service

constructor(
    private router: Router,
    private authService: AuthService,) {
    console.log("SECOND - canActivate") --> this is being printed on the success of the login call
  }

 canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    console.log(this.authService.hasToken(), ">> this.authService.hasToken() <<")
    if (this.authService.hasToken()) {
      return true;
    } else {

      // not logged in so redirect to login page with the return url
      this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
      return false;
    }

  }

在控制台选项卡中,它显示“First”,然后显示“Second - canActivate”,这表明令牌在调用成功时已获取其值,但是,由于某种原因,返回的值hasToken()方法是false


老实说,我不太能找出问题所在,但我会写一些不同的东西,所以我会建议这些,希望它能重构问题。还console.log是异步的,所以不要相信它会以正确的顺序登录。

当使用 RxJS 时,我建议倾向于功能性的并且不使用静态成员变量来传递值。您应该致力于链接所有内容,这样就不会出现任何意外的异步副作用。

这未经测试,但应该是正确的。检查内嵌评论。希望能帮助到你。

private login() {
  this.authService.login(this.loginForm.valid)
  .subscribe((data: any) => { // no need for pipe and map
    console.log("First");
    this.router.navigate(['/app']);
  })
}
export class AuthService {

  public isLoggingIn = new BehaviorSubject<boolean>(false);
  public isLoggedIn = new BehaviorSubject<boolean>(false);

  constructor() { }

  // You were returning Observables, not booleans. Help TypeScript help you - don't use 'any'.
  public login(loginData: { username: string, password: string }): Observable<boolean> { 
    this.clearData();

    this.isLoggingIn.next(true);

    return this.http.post(environment['baseURL'] + '/api/auth/login', loginData)
      .pipe(
        map(
          (data: any) => {
            if (data['token'] && data['user']) {
              this.isLoggedIn.next(true);
              this.isLoggingIn.next(false);
              this.token = data['token'];
              localStorage.setItem('token', this.token);
              localStorage.setItem('usermeta', JSON.stringify(this.userData));
              return true // no 'of'
            } else {
              return false // no 'of'
            }
          }
        ),
        catchError((error: any) => {
          this.isLoggingIn.next(false);
          return of(false) // catchError expects a new observable so we do use 'of' here.
        })
      )
  }

}
export class AuthGuard implements CanActivate {

  constructor(
    private router: Router,
    private authService: AuthService
  ) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> {
    return this.authService.isLoggedIn.pipe(
      // always important to handle the transition state
      // skip if currently logging in (assumes a second emission once logged in)
      skipUntil(this.authService.isLoggingIn.pipe(filter(isLoggingIn => !isLoggingIn))) 
    ).pipe(
      map(isLoggedIn => {
        if (isLoggedIn) {
          return true;
        } else {
          return this.router.createUrlTree(['/login'], { queryParams: { returnUrl: state.url } })
        }
      })
    )
  }

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Angular Guards canActivate 方法总是返回 false? 的相关文章

随机推荐

  • git svn status - 显示未提交到 svn 的更改

    我正在 git svn 中寻找一个命令 该命令将显示我已提交到 git 存储库但尚未提交到中央 svn 存储库的更改 我正在寻找像 svn status 一样工作的东西 但我正在使用 git svn 不幸的是 git svn status不
  • 如何使用 FastAPI 获取 Jinja2 模板中更新的项目列表?

    我正在我的博客上构建一个评论系统 并且我正在呈现这样的现有评论 for comment in comments div class pt 4 div class bg white rounded lg p 3 flex flex col j
  • LARAVEL - 显示存储文件夹中的图像

    我是 Laravel 新手 想知道是否有人可以帮助我完成简单的图像上传 我有一个表单 允许用户创建个人资料并在此过程中上传其个人资料和头像 这一切都很完美 这是我的控制器的代码 if request gt hasFile avatar fi
  • 与任何内容都不匹配的 Glob 会扩展到自身,而不是什么都没有

    我想迭代特殊类型文件夹中的文件 例如 test 所以我写了一些脚本名称for loop for f in test do echo This is f f done After chmod x for loop 我可以开始它 for loo
  • 重新索引不填充 NaN

    我有一个系列 index pd MultiIndex from tuples bar one bar two baz one baz two foo one foo two qux one qux two names first secon
  • 如何使用 DDay.iCal 在 iCal Feed 中设置时区?

    我正在使用创建 iCal feedDDay iCal http www ddaysoftware com Pages Projects DDay iCal 它有效 但我不知道如何设置提要的时区 这是基本代码 iCalendar iCal n
  • FMDB 和加密

    我正在使用 FMDB 来处理 sqlite 并且我希望避免对 SQLCipher 的依赖 如何简单地利用 iOS 内置的 DataProtection 功能 这可能吗 唯一的要求是在手机被盗时保护数据 如果手机使用 PIN 码解锁 则用户可
  • HTML5 画布:调整图像大小

    我正在尝试将图像放置在画布上而不调整其大小 我认为 drawImage img x y 可以解决问题 但它会拉伸图像以填充画布 另外 向 drawImage img x y width height 提供图像的尺寸似乎不起作用 这是我的代码
  • 如何从Openfire获取群聊的离线消息

    有什么办法可以进入xmpp我得到的离线消息MultiUserChat 当我的用户登录并加入房间时 我想要实现群聊 like WhatsApp 还有其他方法可以实现这个请建议 提前致谢 至少在ejjaberd当您进入聊天组时 您必须输入您的最
  • 使用 Jsoup 和适当的 cookie 登录 Facebook

    我目前正在尝试自动废弃我自己的主页以及我登录 Facebook 时可以访问的其他可能页面 但是 在使用下面的代码并设置 cookie 后 我似乎无法 登录 Connection Response res Jsoup connect http
  • 为什么在链表中间插入是O(1)?

    根据维基百科关于链接列表的文章 http en wikipedia org wiki Linked list Linked lists vs arrays 在链表中间插入被认为是 O 1 我认为这将是 O n 您是否不需要找到可能靠近列表末
  • 如何选择DI容器? [复制]

    这个问题在这里已经有答案了 可能的重复 主要 C DI IoC 框架如何比较 https stackoverflow com questions 4581791 how do the major c sharp di ioc framewo
  • .War 可以在 Windows 上部署,但无法在 Linux 服务器 (Tomcat 7) 上部署

    正如标题所介绍的 我尝试使用 Tomcat 7 部署的 War 文件无法在运行 Linux 的计算机上运行 它确实可以在 Windows 上运行 并且当然可以使用 Tomcat 7 进行部署 我试图单独追踪这个问题并在网络上搜索相关问题 包
  • 回显但保留双引号

    我正在尝试创建一个脚本 它将变量 文本回显到文件中 该脚本的一个片段是 echo SUBJECT Text here EMAIL email protected cdn cgi l email protection EMAILMESSAGE
  • 如何修复实体和 POJO 必须有可用的公共构造函数

    当我尝试在使用 sqlite 数据库时启动我的应用程序时 出现此错误 我在不同的文件中有 3 个数据类 Entity tableName movies data class MovieNews PrimaryKey autoGenerate
  • 由于尝试调用虚拟方法“java.lang.String android.content.Context.getPackageName()”,意图失败

    我拥有的 我有一个 RecyclerView 其中包含酒吧 咖啡店的图像 ETC 我想要的 当您单击这些图像之一时 我会向您显示所选位置的信息 但是在您单击所选图像时 应用程序崩溃并显示此错误 尝试调用虚拟方法 java lang Stri
  • 单击 JTextField 中的图标并清除其内容

    我正在尝试创建一个带有图像和提示的 JTextField 文本字段的功能是一个搜索字段 用于搜索一些书籍 现在 我想走得更远一点 我想赋予图像一个功能 例如 如果我单击图像 文本字段中的文本应该被清除 为了实现此实现 我创建了一个新类并使用
  • JS Analytics 电子商务回调

    我找不到任何地方如何使用hitCallback谷歌分析参数ecommerce send 在文档中 它唯一的例子是send pageview 这是我尝试过的代码 ga ecommerce send hitCallback function w
  • 在 python 中使用多个参数进行日志记录

    在 python 日志记录模块中 日志的格式如下 formatter logging Formatter asctime s name s levelname s message s simple example py applicatio
  • 为什么 Angular Guards canActivate 方法总是返回 false?

    我在登录后对用户进行基本身份验证 但发生了奇怪的行为 canActivate 返回 false 即使它是在正确的时间调用的 in 登录组件 private login this authService login this loginFor