简体   繁体   English

登录用户初始值为null Angular 7

[英]Logged in user initial value is null Angular 7

I have a login component with a form and this function to perform the login 我有一个带有表单和此功能的登录组件来执行登录

this.auth.login(this.f.email.value, this.f.password.value)
        .pipe(first())
        .subscribe(
            data => {
                this.router.navigate([this.returnUrl])
            },
            error => {
                this.serverError = error;
                this.loading = false;
            });

this.auth is my authentication service that looks like this this.auth是我的身份验证服务,如下所示

private currentUserSubject: BehaviorSubject<User>
public currentUser: Observable<User>

constructor(private http: HttpClient) {
    this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')))
    this.currentUser = this.currentUserSubject.asObservable()
}

public get currentUserValue(): User {
    return this.currentUserSubject.value
}

login(email: string, password: string) {
    console.log('making login request')
    return this.http.post<any>(`${Config.apiUrl}/login`, { email, password })
        .pipe(map(user => {
            // login successful if there's a jwt token in the response
            if (user && user.token) {
                // store user details and jwt token in local storage to keep user logged in between page refreshes
                localStorage.setItem('currentUser', JSON.stringify(user))
                this.currentUserSubject.next(user)
            }

            return user
        }))
}

It makes a request to my node.js backend which then returns the user if the creds are correct. 它向我的node.js后端发出请求,如果信用证正确则返回用户。 Then angular sets the value of currentUserSubject in AuthorizationService and localStorage to the user values that the server returns. 然后,angular将AuthorizationServicelocalStoragecurrentUserSubject的值设置为服务器返回的用户值。 This all is working how it's supposed to (I assume). 这一切都正在发挥作用(我假设)。

After my login component gets the data back from the authorization service it attempts to route the user to the auth.guard protected page. 在我的登录组件从授权服务获取数据后,它会尝试将用户路由到auth.guard保护页面。 This is what it looks like it my routes. 这就是我的路线。

{
    path: 'user',
    component: UserComponent,
    canActivate: [AuthGuard]
}

My AuthGuard looks like this 我的AuthGuard看起来像这样

constructor(
    private router: Router,
    private authenticationService: AuthenticationService
) { }

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    const currentUser = this.authenticationService.currentUserValue

    if (currentUser) {
        // check if route is restricted by role
        if (route.data.roles && route.data.roles.indexOf(currentUser.role) === -1) {
            // role not authorised so redirect to home page

            this.router.navigate(['/'])
            return false
        }

        // authorised so return true
        return true
    }

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

In AuthGuard canActivate() function currentUser is always null after the initial login request. 在AuthGuard canActivate()函数中, currentUser在初始登录请求后始终为null。 So it redirects me back to my login page. 所以它将我重定向回我的登录页面。

I can't figure out why it's null. 我无法弄清楚为什么它是空的。 The odd thing is, is that after I submit the login form and get redirected back to the login page, if I refresh the browser the currentUser value is not null anymore and the application behaves as I intend it to behave. 奇怪的是,在我提交登录表单并重定向回登录页面之后,如果我刷新浏览器,则currentUser值不再为null,并且应用程序的行为与我打算行为一样。 Is there something I'm missing or doing that I shouldn't be doing that's causing thing? 有没有我缺少或正在做的事情我不应该做那件事造成的?

Here's an image of the process and values that it goes through when I submit the login form 这是我提交登录表单时所经历的过程和值的图像 在此输入图像描述

The solution ended up being simpler than changing the BehaviorSubject to Subject. 解决方案最终比将BehaviorSubject更改为Subject更简单。 In my login component I had the AuthenticationService in the component providers like this. 在我的登录组件中,我在组件提供程序中有这样的AuthenticationService。

@Component({
  selector: 'login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css'],
  providers: [AuthenticationService]
})

All I had to do was remove the service from the providers from all of my components that used it so it would end up looking like this. 我所要做的就是从使用它的所有组件中删除提供程序中的服务,这样最终会看起来像这样。

@Component({
  selector: 'login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})

The thing that tipped me off was the solution to the problem at this link. 让我感到惊讶的是这个链接上的问题解决方案。 https://github.com/angular/angular/issues/11618 https://github.com/angular/angular/issues/11618

In order two share a service between multiple components, you should provide the service at a level higher and not add the service to the providers of both components. 为了使两个组件在多个组件之间共享服务,您应该提供更高级别的服务,而不是将服务添加到两个组件的提供者。

Registering any provider twice will create two independent instances. 两次注册任何提供程序将创建两个独立实例。

So in order to use the AuthorizationService and maintain the state of the logged in user I had to remove it from the component providers. 因此,为了使用AuthorizationService并维护登录用户的状态,我必须将其从组件提供程序中删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM