Я новичок в angular, и я создал небольшое приложение на основе ролей, используя Angular 9 для внешнего интерфейса и Asp. net ядра. когда я вхожу в систему / выхожу из системы, приложение работает правильно без каких-либо проблем, и я могу получить доступ к контроллерам без авторизации из внешнего интерфейса, но когда я хочу получить доступ к контроллеру авторизации («компания»), я получаю ошибку 401.
when I check the "Network" tab in my browser I can see that "WWW-Authenticate: Bearer"
and I checked in
Microsoft Docs , затем я нахожу
Обратите внимание, что ответ включает заголовок Www-Authenticate с задачей, установленной на Bearer. Это означает, что сервер ожидает токен-носитель.
Я почти уверен, что проблема не в бэкэнде, потому что я также проверил бэкэнд с помощью Postman, и он работает правильно
Итак Я помещаю сюда код
auth.service.ts:
@Injectable({
providedIn: 'root'
})
export class AuthService {
baseUrl = environment.apiUrl + 'authentication/'; //environment.apiUrl + 'auth/';
jwtHelper = new JwtHelperService();
decodedToken: any;
currentUser: User;
//================================================================================================
constructor(private myalertService: MyalertService,private http: HttpClient) {}
//================================================================================================
login(model: any) {
return this.http.post(this.baseUrl + 'login', model).pipe(
map((response: any) => {
const user = response;
if (user) {
localStorage.setItem('token', user.user.token);
localStorage.setItem('user', JSON.stringify(user.user));
this.decodedToken = this.jwtHelper.decodeToken(user.user.token);
this.currentUser = user.user;
}
})
);
}
//================================================================================================
loggedIn() {
const token = localStorage.getItem('token');
return !this.jwtHelper.isTokenExpired(token);
}
//================================================================================================
roleMatch(allowedRoles): boolean {
let isMatch = false;
const userRoles = this.decodedToken.role as Array<string>;
allowedRoles.forEach(element => {
if (userRoles.includes(element)) {
isMatch = true;
return;
}
});
return isMatch;
}
//===================================================================================================
}
company.service.ts:
@Injectable({
providedIn: 'root'
})
export class CompanyService {
result = false;
baseUrl = environment.apiUrl + 'companies';
constructor(private myalertService: MyalertService,private http: HttpClient ) { }
//=============================================================================================
getCompaniesList(page?,itemsPerPage?,srchMdl?): Observable<PaginatedResult<Company[]>> {
const paginatedResult : PaginatedResult<Company[]> = new PaginatedResult<Company[]>();
let params = new HttpParams();
if (page != null && itemsPerPage != null) {
params = params.append('pageNumber', page);
params = params.append('pageSize', itemsPerPage);
}
if (srchMdl != null) {
if(srchMdl.name != "" && srchMdl.name != null ) params = params.append('name',srchMdl.name);
if(srchMdl.address != "" && srchMdl.address != null ) params = params.append('address',srchMdl.address);
if(srchMdl.country != "" && srchMdl.country != null) params = params.append('country',srchMdl.country);
if(srchMdl.searchOperator != "" && srchMdl.searchOperator != null) params = params.append('searchOperator',srchMdl.searchOperator); else params = params.append('searchOperator','AND');
if(srchMdl.sortBasedOn != "" && srchMdl.sortBasedOn != null) params = params.append('orderBy',srchMdl.sortBasedOn);
}
return this.http.get<Company[]>(this.baseUrl , { observe: 'response', params},)
.pipe(
map(response => {
paginatedResult.result = response.body;
if (response.headers.get('X-Pagination') != null) {
paginatedResult.pagination = JSON.parse(response.headers.get('X-Pagination'));
}
return paginatedResult;
})
);
}
//=============================================================================================
}
company.resolver.ts:
@Injectable()
export class CompanyResolver implements Resolve<Company[]> {
pageNumber = 0;
pageSize = 5;
constructor(private companyService: CompanyService, private router: Router,
private alertify: MyalertService) {}
resolve(route: ActivatedRouteSnapshot): Observable<Company[]> {
return this.companyService.getCompaniesList(this.pageNumber, this.pageSize).pipe(
catchError(error => {
this.alertify.error('Problem retrieving data');
this.router.navigate(['/home']);
return of(null);
})
);
}
}
hasRole.directive.ts:
@Directive({
selector: '[appHasRole]'
})
export class HasRoleDirective implements OnInit {
@Input() appHasRole: string[];
isVisible = false;
constructor(
private viewContainerRef: ViewContainerRef,
private templateRef: TemplateRef<any>,
private authService: AuthService) { }
ngOnInit() {
const userRoles = this.authService.decodedToken.role as Array<string>;
if (!userRoles) {
this.viewContainerRef.clear();
}
if (this.authService.roleMatch(this.appHasRole)) {
if (!this.isVisible) {
this.isVisible = true;
this.viewContainerRef.createEmbeddedView(this.templateRef);
} else {
this.isVisible = false;
this.viewContainerRef.clear();
}
}
}
}
auth.guard.ts:
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor( private authService: AuthService,
private router: Router,
private alertify: MyalertService) {}
canActivate(next: ActivatedRouteSnapshot): boolean {
const roles = next.firstChild.data['userRoles'] as Array<string>;
console.log('auth.guard.ts');
console.log(roles);
if (roles) {
const match = this.authService.roleMatch(roles);
if (match) {
return true;
} else {
this.alertify.error('You are not authorized to access this area');
}
}
if (this.authService.loggedIn()) {
return true;
}
this.alertify.error('You shall not pass!!!');
this.router.navigate(['/company']);
return false;
}
}
routes.ts:
export const appRoutes: Routes = [
{path: '', component: HomeComponent},
{
path: '',
runGuardsAndResolvers: 'always',
canActivate: [AuthGuard],
children: [
{path: 'company', component: CompanyComponent, data: {userRoles: ['Administrator', 'Manager']}},
{path: 'register', component: RegisterComponent },
{path: 'memberList', component: MemberListComponent},
{path: 'admin', component: AdminPanelComponent, data: {userRoles: ['Administrator', 'Manager']}},
]
},
{path: '**', redirectTo: '', pathMatch: 'full'},
];
приложение .module.ts:
export function tokenGetter() {
return localStorage.getItem('token');
}
@NgModule({
declarations: [
CompanyComponent,
HomeComponent,
NavBarComponent,
HasRoleDirective
],
imports: [
ReactiveFormsModule,
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatSliderModule,
MatButtonModule,
MatIconModule,
MatDividerModule,
MatSnackBarModule,
MatTableModule,
HttpClientModule,
FormsModule,
MatFormFieldModule,
MatCardModule,
MatInputModule,
MatToolbarModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSelectModule,
MatRadioModule,
FlexLayoutModule,
RouterModule.forRoot(appRoutes),
JwtModule.forRoot({
config: {
//This automatically adds the token to the request.
tokenGetter: tokenGetter,
whitelistedDomains:['localhost:5001'],
blacklistedRoutes: ['localhost:5001/api/authentication'],
}
})
],
providers: [
CompanyResolver,
AuthService,
AuthGuard,
CompanyService
],
bootstrap: [
AppComponent
]
})
export class AppModule { }
navBar.component.ts:
xport class NavBarComponent implements OnInit {
model: any = {};
constructor(
private authService: AuthService ,
private alertify: MyalertService ,
private router: Router
) {}
ngOnInit() {
this.model.username = 'abcdefgh';
this.model.password = 'Pass12345678';
}
login() {
this.authService.login(this.model).subscribe(next => {
this.alertify.success('Logged in successfully');
}, error => {
this.alertify.error(error);
}, () => {
});
}
loggedIn() {
const token = localStorage.getItem('token');
return !!token;
}
logout() {
localStorage.removeItem('token');
localStorage.removeItem('user');
this.authService.decodedToken = null;
this.authService.currentUser = null;
this.alertify.success('logged out');
this.router.navigate(['/home']);
}
}
navBar.component. html:
<mat-toolbar color="primary">
<span class="fill-remaining-space"></span>
<button mat-button routerLink="login">Login</button>
<button mat-button (click)="logout()">Logout</button>
<ul *ngIf="loggedIn()" >
<button *appHasRole="['Admin','Manager']" mat-button [routerLink]="['/company']">company Manager</button>
<button mat-button [routerLink]="['/memberList']">member List</button>
</ul>
<form #loginForm="ngForm" *ngIf="!loggedIn()" class="form-inline my-2 my-lg-0" (ngSubmit)="login()">
<mat-form-field appearance="legacy" >
<input matInput name="username" placeholder="Username " [(ngModel)]="model.username" >
</mat-form-field>
<mat-form-field appearance="legacy" >
<input matInput name="password" placeholder="Password " [(ngModel)]="model.password">
</mat-form-field>
<button mat-raised-button color="accent" type="submit"> Login </button>
</form>
</mat-toolbar>