Я работаю над своим первым ASP. NET Базовым веб-приложением со SPA, использующим Angular 9. Это мой первый опыт работы с Angular, я следую учебному пособию по Pluralsight. Но у меня были трудности с тем, чтобы оставаться на той же странице после входа в систему. Я использую IdentityServer4, ASP. NET Identity и oid c -клиента для моего Angular бита.
Итак, я запускаю приложение с "https://localhost: 44392 / ». Итак, изначально это нормально. Проблема возникает, когда я go, например, "https://localhost: 44392 / search ". Если я go через панель навигации, которая имеет [routerLink] = "['/ search']", то проблем нет. Однако, если я просто напишу «https://localhost: 44392 / search » в адресной строке браузера, это вызовет еще один вход (он не запрашивает учетные данные, хотя мой id_token все еще обычно действителен) , Но после подписания он возвращается на домашнюю страницу (он же "https://localhost: 44392 / ").
Это поведение началось только после добавления oid c -client и guardService. , Я попытался выполнить поиск в Интернете, но мне кажется, что я что-то упустил, потому что я не могу заставить вещи работать с заданными ответами.
Итак, вот мои занятия
import { Injectable } from '@angular/core';
import {UserManager, User} from 'oidc-client';
import { environment } from 'src/environments/environment';
import { ReplaySubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class OpenIdConnectService {
private userManager: UserManager = new UserManager(environment.openIdConnectSettings);
private currentUser: User;
userLoaded$ = new ReplaySubject<boolean>(1);
get userAvailable(): boolean {
return this.currentUser != null;
}
get user(): User {
return this.currentUser;
}
constructor() {
this.userManager.clearStaleState();
this.userManager.events.addUserLoaded(user => {
if (!environment.production) {
console.log('User loaded: ', user);
}
this.currentUser = user;
this.userLoaded$.next(true);
});
this.userManager.events.addUserUnloaded(() => {
if (!environment.production) {
console.log('User unloaded.');
}
this.currentUser = null;
this.userLoaded$.next(false);
});
}
triggerSignIn(url: string){ //originally without the parameter url
this.userManager.signinRedirect().then(function () {
if (!environment.production) {
console.log('Redirection to signin triggered.');
}
data: {redirect_url: url} //I added this because I saw it in a reply in SO, but doesn't work.
});
}
handleCallBack(){
this.userManager.signinRedirectCallback().then(function (user){
if (!environment.production) {
console.log('Callback after signin handled.', user);
}
});
}
triggerSignOut() {
this.userManager.signoutRedirect().then(function (resp) {
if (!environment.production) {
console.log('Redirection to sign out triggered.', resp);
}
});
}
}
import { Component, OnInit } from '@angular/core';
import { OpenIdConnectService } from '../shared/open-id-connect.service';
import { Router } from '@angular/router';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-signin-oidc',
templateUrl: './signin-oidc.component.html',
styleUrls: ['./signin-oidc.component.scss']
})
export class SigninOidcComponent implements OnInit {
constructor(private openIdConnectService: OpenIdConnectService,
private router: Router) { }
ngOnInit() {
this.openIdConnectService.userLoaded$.subscribe((userLoaded) => {
if (userLoaded) {
this.router.navigate(['./']);
}
else {
if (!environment.production) {
console.log("An error happened: user wasn't loaded.");
}
}
});
this.openIdConnectService.handleCallBack();
}
}
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { OpenIdConnectService } from './open-id-connect.service';
@Injectable({
providedIn: 'root'
})
export class RequireAuthenticatedUserRouteGuardService implements CanActivate {
constructor(private openIdConnectService: OpenIdConnectService,
private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {//route and state were not part of the original example. I just added it in an attempt to pass is as param to triggerSignIn
if (this.openIdConnectService.userAvailable) {
return true;
}
else
{
//trigger signin
this.openIdConnectService.triggerSignIn(state.url);
return false;
}
}
}
app.module.ts
//Lots of other imports
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { ComponentsModule } from "./components/components.module";
import { ProfileComponent } from './profile/profile.component';
import { SearchComponent } from './search/search.component';
import { MonitoringComponent } from './monitoring/monitoring.component';
import { OpenIdConnectService } from './shared/open-id-connect.service';
import { SigninOidcComponent } from './signin-oidc/signin-oidc.component';
import { RequireAuthenticatedUserRouteGuardService } from './shared/require-authenticated-user-route-guard.service';
import { AddAuthorizationHeaderInterceptor } from './shared/add-authorization-header-interceptor';
@NgModule({
declarations: [
//there are other components but deleted for brevity
AppComponent,
HomeComponent,
ProfileComponent,
SearchComponent,
MonitoringComponent,
SigninOidcComponent
],
imports: [
HttpClientModule,
ComponentsModule,
RouterModule.forRoot([
{ path: '', component: HomeComponent, pathMatch: 'full', canActivate: [RequireAuthenticatedUserRouteGuardService] },
{ path: 'profile/:ytChannelId', component: ProfileComponent, canActivate: [RequireAuthenticatedUserRouteGuardService] },
{ path: 'search', component: SearchComponent, canActivate: [RequireAuthenticatedUserRouteGuardService] },
{ path: 'monitoring', component: MonitoringComponent, canActivate: [RequireAuthenticatedUserRouteGuardService] },
{ path: 'monitoring/:ytVideoId', component: MonitoringComponent, canActivate: [RequireAuthenticatedUserRouteGuardService] },
{ path: 'signin-oidc', component: SigninOidcComponent },
]),
//there are more things deleted for brevity
],
providers: [
{
provide: PERFECT_SCROLLBAR_CONFIG,
useValue: DEFAULT_PERFECT_SCROLLBAR_CONFIG
},
{
provide: HTTP_INTERCEPTORS,
useClass: AddAuthorizationHeaderInterceptor,
multi: true
},
OpenIdConnectService,
RequireAuthenticatedUserRouteGuardService
],
bootstrap: [AppComponent]
})
export class AppModule { }
import { Injectable } from "@angular/core";
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from "@angular/common/http";
import { OpenIdConnectService } from "./open-id-connect.service";
import { Observable } from "rxjs";
@Injectable()
export class AddAuthorizationHeaderInterceptor implements HttpInterceptor {
constructor (private openIdConnectService: OpenIdConnectService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
//add the access token as bearer token
request = request.clone(
{ setHeaders: {Authorization: this.openIdConnectService.user.token_type
+ " " + this.openIdConnectService.user.access_token}}
);
return next.handle(request);
}
}
И, наконец, мой environment.ts
export const environment = {
production: false,
apiUrl: 'https://localhost:44392/api/v1/',
openIdConnectSettings: {
authority: 'https://localhost:44350/',
client_id: 'peraClient',
redirect_uri: 'https://localhost:44392/signin-oidc',
scope: 'openid profile roles peraAPI',
response_type: 'id_token token',
post_logout_redirect_uri: 'https://localhost:44392/',
automaticSilentRenew: true,
silent_redirect_uri: 'https://localhost:44392/redirect-silentrenew'
},
pageSize: 20
};
Я подозреваю, что проблема с охраной, но я просто не знаю достаточно знать лучше Любое понимание очень ценится.
Спасибо
ОБНОВЛЕНИЕ: Итак, я наконец-то обнаружил, что именно вызывает перенаправление. Именно эта строка this.router.navigate(['./']);
в signin-oid c .component.ts, но я не знаю, что поместить туда вместо этого, чтобы сделать ее go для URL, который вызвал вход в систему.
Имейте в виду, что это происходит только тогда, когда я пишу URL-адрес непосредственно в адресной строке браузера, и не происходит, когда я использую панель навигации в своем приложении. Есть идеи, как это решить? Я попытался написать this.router.navigate([this.location.back()]);
, но это создает al oop с идентификатором входа c вместо отправки меня на страницу, которая вызвала логин (пример https://localhost: 44392 / search )