尝试通过应用程序实施身份验证。我试图使用拦截器实现伪造的身份验证服务。但是,每当我登录时,都会出现以下错误
posts:1无法加载资源:服务器响应状态为404(未找到) XHR无法加载:POST“ http://localhost:4200/api/authenticate”。
我尝试从这里http://jasonwatmore.com/post/2018/05/23/angular-6-jwt-authentication-example-tutorial
假后端
import { Injectable } from '@angular/core';
import { HttpRequest, HttpResponse, HttpHandler, HttpEvent,
HttpInterceptor, HTTP_INTERCEPTORS } from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { delay, mergeMap, materialize, dematerialize } from 'rxjs/operators';
@Injectable()
export class FakeBackendInterceptor implements HttpInterceptor {
constructor() { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let testUser = { id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User' };
console.log("**************************************************");
// wrap in delayed observable to simulate server api call
return of(null).pipe(mergeMap(() => {
// authenticate
if (request.url.endsWith('/api/authenticate') && request.method === 'POST') {
if (request.body.username === testUser.username && request.body.password === testUser.password) {
// if login details are valid return 200 OK with a fake jwt token
let body = {
id: testUser.id,
username: testUser.username,
firstName: testUser.firstName,
lastName: testUser.lastName,
token: 'fake-jwt-token'
};
return of(new HttpResponse({ status: 200, body }));
} else {
// else return 400 bad request
return throwError({ error: { message: 'Username or password is incorrect' } });
}
}
// get users
if (request.url.endsWith('/posts') && request.method === 'GET') {
// check for fake auth token in header and return users if valid, this security is implemented server side in a real application
if (request.headers.get('Authorization') === 'Bearer fake-jwt-token') {
return of(new HttpResponse({ status: 200, body: [testUser] }));
} else {
// return 401 not authorised if token is null or invalid
return throwError({ error: { message: 'Unauthorised' } });
}
}
// pass through any requests not handled above
return next.handle(request);
}))
// call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
.pipe(materialize())
.pipe(delay(500))
.pipe(dematerialize());
}
}
export let fakeBackendProvider = {
// use fake backend in place of Http service for backend-less development
provide: HTTP_INTERCEPTORS,
useClass: FakeBackendInterceptor,
multi: true
};
登录组件
`
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import {FormGroup,FormControl, Validators,FormBuilder} from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { AuthenticationService } from 'src/app/services/authentication.service';
import { first } from 'rxjs/internal/operators/first';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
loading = false;
submitted = false;
returnUrl: string;
error = '';
constructor(
private formBuilder: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private authenticationService: AuthenticationService) {}
ngOnInit() {
this.loginForm = this.formBuilder.group({
username: ['', Validators.required],
password: ['', Validators.required]
});
// reset login status
this.authenticationService.logout();
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
}
// convenience getter for easy access to form fields
get f() { return this.loginForm.controls; }
onSubmit() {
this.submitted = true;
// stop here if form is invalid
if (this.loginForm.invalid) {
return;
}
this.loading = true;
this.authenticationService.login(this.f.username.value, this.f.password.value)
.pipe(first())
.subscribe(
data => {
this.router.navigate([this.returnUrl]);
},
error => {
this.error = error;
this.loading = false;
});
}
}
`
应用模块
`
import { BrowserModule } from '@angular/platform-browser';
import {FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AppComponent } from './app.component';
import { ProductsComponent } from 'src/app/products.component';
import { ProductComponent } from './product/product.component';
import { ProductsService } from 'src/app/products.service';
import { DescriptionPipe } from 'src/app/description.pipe';
import { FavouriteComponent } from './favourite/favourite.component';
import { PanelComponent } from './panel/panel.component';
import { InputFormatDirective } from './input-format.directive';
import { ContactFormComponent } from './contact-form/contact-form.component';
import { SignupFormComponent } from './signup-form/signup-form.component';
import { NewcourseformcomponentComponent } from './newcourseformcomponent/newcourseformcomponent.component';
import { PostsComponent } from './posts/posts.component';
import { NavbarComponent } from './navbar/navbar.component';
import { HomeComponent } from './home/home.component';
import { NotfoundComponent } from './notfound/notfound.component';
import { RouterModule, Routes } from '@angular/router';
import { CreateEditComponent } from 'src/app/create-edit/create-edit.component';
import { AdminComponent } from './admin/admin.component';
import { LoginComponent } from './login/login.component';
// used to create fake backend
import { FakeBackendInterceptor } from 'src/app/helper/fake-backend';
import { ErrorInterceptor} from 'src/app/helper/error.interceptor';
import { JwtInterceptor} from 'src/app/helper/jwt.interceptor';
@NgModule({
declarations: [
AppComponent,ProductsComponent, ProductComponent,DescriptionPipe, FavouriteComponent,
PanelComponent, InputFormatDirective, ContactFormComponent, SignupFormComponent, NewcourseformcomponentComponent,
PostsComponent, NavbarComponent, HomeComponent, NotfoundComponent, CreateEditComponent, AdminComponent, LoginComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
RouterModule.forRoot([
{path: '', component: HomeComponent },
// {path: 'posts/:id ', component: CreateEditComponent },
{path: 'posts/:id/:title', component: CreateEditComponent },
{ path: 'admin', component: AdminComponent },
{ path: 'login', component: LoginComponent },
{path: 'posts', component: PostsComponent },
{path: '**', component: NotfoundComponent }
])
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
// provider used to create fake backend
FakeBackendInterceptor],
bootstrap: [AppComponent]
})
export class AppModule { }
`
身份验证服务
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class AuthenticationService {
constructor(private http: HttpClient) { }
login(username: string, password: string) {
return this.http.post<any>(`/api/authenticate`, { username, 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));
}
return user;
}));
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
}
}
答案 0 :(得分:0)
您可以使用ngxMocks
git clone https://github.com/abdelrahman-haridy01/ngx-mocks
克隆存储库。npm i
npm start
。导航到http://localhost:4200/。如果您更改任何源文件,该应用程序将自动重新加载。也请检查文档 https://github.com/abdelrahman-haridy01/ngx-mocks/blob/master/README.md