Angular 10 - 端点访问可以从邮递员而不是 Angular
Angular 10 - Endpoint access works from postman but not from Angular
我有一个前端 angular 应用程序,我是 运行 来自 localhost:4200
我还有一个后端 api 应用程序,我是 运行 来自 localhost:8080
我也有 postman 运行,我在创建 angular 前端之前用它来测试这些端点。
我的问题是 localhost:8080/ 在通过邮递员调用 localhost:8080/sign-in 后有效,但在通过我的 angular 前端调用 localhost:8080/sign-in。
我可以通过 postman 使用路由 localhost:8080/sign-in,它会登录用户并设置 session cookie。
这是结果:
响应:
It returns the user object here as JSON
Header:
Access-Control-Allow-Origin:
Access-Control-Expose-Headers Set-Cookie
Content-Type application/json; charset=UTF-8
Set-Cookie session_=RTZCYXOW3ILNKOOZQOZKEC4Y3J3YPOVUGGA6TI46ZLRX5UAWS77O7TGE74ZEFQEOTZLTCKRTCYJJ57OT24KUPPMBPYOXWBZRXF54PGA; Path=/; Expires=Sun, 29 Nov 2020 09:33:43 GMT; Max-Age=604800
Vary Origin
X-Request-Id gTCSwvwm4m8oLDqy99fkhqAeWgrddnjl
Date Sun, 22 Nov 2020 09:33:43 GMT
Content-Length 658
然后我有另一个端点:localhost:8080/ 需要用户登录才能访问。
如果他们已登录:
响应:
“Valid”
Header:
Access-Control-Allow-Origin:
Access-Control-Expose-Headers Set-Cookie
Content-Type application/json; charset=UTF-8
Vary Origin
X-Request-Id mRy9w40wEKx4zI2h4JuaMAZ2CppbvzHR
Date Sun, 22 Nov 2020 09:34:47 GMT
Content-Length 8
如果他们没有登录:
响应:
"access denied”
Header:
Access-Control-Allow-Origin:
Access-Control-Expose-Headers: Set-Cookie
Content-Type: application/json; charset=UTF-8
Vary: Origin
X-Request-Id: eRQJwPIXQnAOavpgkhobNoJnKgbQmDpE
Date: Sun, 22 Nov 2020 09:36:11 GMT
Content-Length: 18
现在,我可以从我的 angular 应用程序调用 localhost:8080/sign-in 端点。
这确实 return 用户作为 JSON object 与邮递员相同。
但是我不认为它正在设置 cookie,因此当我从我的 angular 应用程序调用 localhost:4200/ 端点时,它会给出错误:[ HTTP/1.1 403 Forbidden 1ms] 如果我在注销时尝试访问该端点,这与我从邮递员那里得到的错误相同。
我确保在尝试 localhost:8080/ 之前调用了 localhost:8080/sign-in angular 前端(先尝试设置 cookie)
这是我后台的相关配置api:
这是session商店配置
store.Options(sessions.Options{
Path: "/",
MaxAge: 86400 * 7,
HttpOnly: false,
})
这是中间件配置
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"http://localhost:4200"},
AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAccessControlAllowCredentials},
ExposeHeaders: []string{echo.HeaderSetCookie},
AllowCredentials: true,
}))
这是我在 angular 前端登录的服务和组件:
auth-http.service.ts
login(email: string, password: string): Observable<Response> {
let headers = new HttpHeaders({'Content-Type': 'application/json'});
headers.set('access-control-allow-origin',"http://localhost:4200/");
headers.set('withCredentials', "true");
let result = this.http.post<any>(`${API_URL}/sign-in`, { email: email, password: password }, { headers });
return result;
}
test(): Observable<Response> {
let headers = new HttpHeaders({'Content-Type': 'application/json'});
headers.set('access-control-allow-origin',"http://localhost:4200/");
headers.set('withCredentials', "true");
let result = this.http.get<any>(`${API_URL}/`, { headers });
return result;
}
auth.service.ts
login(email: string, password: string): Observable<UserModel> {
this.isLoadingSubject.next(true);
return this.authHttpService.login(email, password).pipe(
map((result: Response) => {
// undefined
console.log(result.headers)
console.log(result);
// pass in the auth here
return result;
}),
//switchMap(() => this.getUserByToken()),
catchError((err) => {
console.error('err', err); // here
return of(undefined);
}),
finalize(() => this.isLoadingSubject.next(false))
);
}
test(): Observable<any> {
this.isLoadingSubject.next(true);
return this.authHttpService.test().pipe(
map((result: Response) => {
return result;
}),
//switchMap(() => this.getUserByToken()),
catchError((err) => {
console.error('err', err); // here
return of(undefined);
}),
finalize(() => this.isLoadingSubject.next(false))
);
}
login.component.ts
submit() {
this.hasError = false;
const loginSubscr = this.authService
.login(this.f.email.value, this.f.password.value)
.pipe(first())
.subscribe((user: UserModel) => {
console.log(user);
if (user) {
this.router.navigate([this. returnUrl]);
} else {
this.hasError = true;
}
});
this.unsubscribe.push(loginSubscr);
}
test() {
this.hasError = false;
const loginSubscr = this.authService
.test()
.pipe(first())
.subscribe((res: any) => {
console.log(res);
if (res) {
console.log(res)
} else {
this.hasError = true;
}
});
this.unsubscribe.push(loginSubscr);
}
为了测试 localhost:8080/ 端点,我刚刚在登录 html 组件上创建了一个测试按钮,然后调用测试服务以查看它是否可以访问localhost:8080/ 端点。
通过使用:
const options = {withCredentials: true, 'access-control-allow-origin': "http://localhost:4200/", 'Content-Type': 'application/json'}
而不是另一种设置方式headers。
我有一个前端 angular 应用程序,我是 运行 来自 localhost:4200
我还有一个后端 api 应用程序,我是 运行 来自 localhost:8080
我也有 postman 运行,我在创建 angular 前端之前用它来测试这些端点。
我的问题是 localhost:8080/ 在通过邮递员调用 localhost:8080/sign-in 后有效,但在通过我的 angular 前端调用 localhost:8080/sign-in。
我可以通过 postman 使用路由 localhost:8080/sign-in,它会登录用户并设置 session cookie。 这是结果:
响应:
It returns the user object here as JSON
Header:
Access-Control-Allow-Origin:
Access-Control-Expose-Headers Set-Cookie
Content-Type application/json; charset=UTF-8
Set-Cookie session_=RTZCYXOW3ILNKOOZQOZKEC4Y3J3YPOVUGGA6TI46ZLRX5UAWS77O7TGE74ZEFQEOTZLTCKRTCYJJ57OT24KUPPMBPYOXWBZRXF54PGA; Path=/; Expires=Sun, 29 Nov 2020 09:33:43 GMT; Max-Age=604800
Vary Origin
X-Request-Id gTCSwvwm4m8oLDqy99fkhqAeWgrddnjl
Date Sun, 22 Nov 2020 09:33:43 GMT
Content-Length 658
然后我有另一个端点:localhost:8080/ 需要用户登录才能访问。
如果他们已登录:
响应:
“Valid”
Header:
Access-Control-Allow-Origin:
Access-Control-Expose-Headers Set-Cookie
Content-Type application/json; charset=UTF-8
Vary Origin
X-Request-Id mRy9w40wEKx4zI2h4JuaMAZ2CppbvzHR
Date Sun, 22 Nov 2020 09:34:47 GMT
Content-Length 8
如果他们没有登录:
响应:
"access denied”
Header:
Access-Control-Allow-Origin:
Access-Control-Expose-Headers: Set-Cookie
Content-Type: application/json; charset=UTF-8
Vary: Origin
X-Request-Id: eRQJwPIXQnAOavpgkhobNoJnKgbQmDpE
Date: Sun, 22 Nov 2020 09:36:11 GMT
Content-Length: 18
现在,我可以从我的 angular 应用程序调用 localhost:8080/sign-in 端点。 这确实 return 用户作为 JSON object 与邮递员相同。
但是我不认为它正在设置 cookie,因此当我从我的 angular 应用程序调用 localhost:4200/ 端点时,它会给出错误:[ HTTP/1.1 403 Forbidden 1ms] 如果我在注销时尝试访问该端点,这与我从邮递员那里得到的错误相同。
我确保在尝试 localhost:8080/ 之前调用了 localhost:8080/sign-in angular 前端(先尝试设置 cookie)
这是我后台的相关配置api:
这是session商店配置
store.Options(sessions.Options{
Path: "/",
MaxAge: 86400 * 7,
HttpOnly: false,
})
这是中间件配置
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"http://localhost:4200"},
AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAccessControlAllowCredentials},
ExposeHeaders: []string{echo.HeaderSetCookie},
AllowCredentials: true,
}))
这是我在 angular 前端登录的服务和组件:
auth-http.service.ts
login(email: string, password: string): Observable<Response> {
let headers = new HttpHeaders({'Content-Type': 'application/json'});
headers.set('access-control-allow-origin',"http://localhost:4200/");
headers.set('withCredentials', "true");
let result = this.http.post<any>(`${API_URL}/sign-in`, { email: email, password: password }, { headers });
return result;
}
test(): Observable<Response> {
let headers = new HttpHeaders({'Content-Type': 'application/json'});
headers.set('access-control-allow-origin',"http://localhost:4200/");
headers.set('withCredentials', "true");
let result = this.http.get<any>(`${API_URL}/`, { headers });
return result;
}
auth.service.ts
login(email: string, password: string): Observable<UserModel> {
this.isLoadingSubject.next(true);
return this.authHttpService.login(email, password).pipe(
map((result: Response) => {
// undefined
console.log(result.headers)
console.log(result);
// pass in the auth here
return result;
}),
//switchMap(() => this.getUserByToken()),
catchError((err) => {
console.error('err', err); // here
return of(undefined);
}),
finalize(() => this.isLoadingSubject.next(false))
);
}
test(): Observable<any> {
this.isLoadingSubject.next(true);
return this.authHttpService.test().pipe(
map((result: Response) => {
return result;
}),
//switchMap(() => this.getUserByToken()),
catchError((err) => {
console.error('err', err); // here
return of(undefined);
}),
finalize(() => this.isLoadingSubject.next(false))
);
}
login.component.ts
submit() {
this.hasError = false;
const loginSubscr = this.authService
.login(this.f.email.value, this.f.password.value)
.pipe(first())
.subscribe((user: UserModel) => {
console.log(user);
if (user) {
this.router.navigate([this. returnUrl]);
} else {
this.hasError = true;
}
});
this.unsubscribe.push(loginSubscr);
}
test() {
this.hasError = false;
const loginSubscr = this.authService
.test()
.pipe(first())
.subscribe((res: any) => {
console.log(res);
if (res) {
console.log(res)
} else {
this.hasError = true;
}
});
this.unsubscribe.push(loginSubscr);
}
为了测试 localhost:8080/ 端点,我刚刚在登录 html 组件上创建了一个测试按钮,然后调用测试服务以查看它是否可以访问localhost:8080/ 端点。
通过使用:
const options = {withCredentials: true, 'access-control-allow-origin': "http://localhost:4200/", 'Content-Type': 'application/json'}
而不是另一种设置方式headers。