FlaskLogin没有将cookies设置为angular浏览器?

2024-10-01 07:50:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Angular 6&Python Flask构建一个fullstack web项目,主要使用Flask安全扩展。在

目前,我尝试实现一个用户登录系统,使用login_user()(Flask login的方法)。基本上,login_user()可以工作,但我在浏览器上看不到任何会话cookie。在

如文档所述,session对象的每个更改/新实例都会相应地设置/修改cookies,因此login_user()会创建一个session的新实例。在

我正在使用'http://127.0.0.1:5000/'在'http://127.0.0.1:4200'(角度默认端口)和Flask上运行和测试项目。在

作为最后的手段,我尝试在没有任何实际前端的情况下构建一个Flask应用程序,从http://127.0.0.1:5000/运行和测试它,它确实奏效了。我已经设法看到了login_user()应该从一开始就设置的cookies。在

主要是,我的问题是,为什么它不能和Angular一起工作? 前端代码:

export class Login {
    constructor(private userSerivce : UserService, private router : Router) {}

    outputMessage : string = null;

    loginOnSubmit(form : FormGroup): void {
        let formDict = {
            "email" : form.controls["email"].value,
            "password" : form.controls["password"].value
        }
        this.userSerivce.loginOnSubmit(formDict).subscribe({
            next : value => {
                //whatever, still didn't get here
            },
            error : response => {this.outputMessage = response.error}
        })
    }

后台登录功能:

^{pr2}$

模型与文档所示完全相同,我甚至在我的空瓶应用程序中使用了相同的代码(相同的类和数据库,正如我所说的,它起作用了)。在


Tags: 实例代码文档form应用程序httpflaskvalue
1条回答
网友
1楼 · 发布于 2024-10-01 07:50:30

无法使用服务器会话设置浏览器Cookie。你必须在回复中发送cookies。如果要在响应中设置cookies,可以执行以下操作:

from flask import make_response # and your other stuff
# ... other imports ...
def login():
# ... some authentication code here to get your access_token (like a jwt)...
    resp = make_response(redirect('http://localhost:4200')) # your angular app
    resp.set_cookie('token', access_token) # set the cookie on the response header for the browser to extract
    return resp # return the response with the new cookie attached

由于您的客户机应用程序与服务器应用程序不在同一个域中,因此设置会话对您想要的身份验证方式没有帮助。JWT在客户端和服务器之间来回传递的方式是最好的。在

您可以尝试做的一件事(如果您想在前端设置某种身份验证)是验证您的用户将JWT返回Angular。然后,您可以设置一个http头来每次后端。后端将解析请求并从头中提取JWT。然后,您将使用该头通过解密JWT来验证用户对后端的请求。这方面有很多文献。我会在这篇文章的最后放一些好的教程。在

您可以使用(角度)an HttpInterceptor。像这样:

^{pr2}$

您可以使用如下身份验证服务:

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { CookieService } from 'ngx-cookie-service';
import { map } from 'rxjs/operators';
import { environment } from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  redirectUrl: string;
  // cookie service from ngx-cookie-service
  constructor(private http: HttpClient, private cookieService: CookieService) { }

  checkToken() {
    return this.cookieService.check('token');
  }

  getToken() {
    return this.cookieService.get('token');
  }

  loginWithUsernameAndPassword(userName: string, password: string) {
    return this.http.post<any>(`${environment.API_URL}/auth/login`,
        new HttpParams({fromObject: {userName, password}}),
        {
          headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
        }
      ).pipe(map(user => {
        if (user && user.token) {
          this.cookieService.set('token', user.token);
        }
        return user;
      }));
  }

  logout() {
    this.cookieService.delete('token');
  }

  isLoggedIn() {
    return this.cookieService.check('token');
  }

  registerWithUsernameAndPassword(userName, password, email) {
    return this.http.post<any>(`${environment.API_URL}/auth/create`,
      new HttpParams({fromObject: {userName, password, email}}),
      {
        headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
      }
    )
      .pipe(map(user => {
        console.log(user);
        return user;
      }));
  }

}

在您的AppModule中,您可以指定一个名为HTTP_INTERCEPTORS的提供程序,并使用您在本例中创建的HttpInterceptor,我将其称为TokenInterceptor

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing/app-routing.module';

import { SharedModule } from './shared/shared.module';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { CookieService } from 'ngx-cookie-service';
import { AuthService } from './auth/auth.service';
import { TokenInterceptor } from './interceptors/token.interceptor';

@NgModule({
  imports: [
    BrowserModule,
    AppRoutingModule,
    SharedModule,
    HttpClientModule
  ],
    declarations: [
    AppComponent,
  ],
  exports: [],
  providers: [
    AuthService,
    CookieService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: TokenInterceptor,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

拦截器的一个很好的参考:https://angular.io/api/common/http/HttpInterceptor 和:https://medium.com/@ryanchenkie_40935/angular-authentication-using-the-http-client-and-http-interceptors-2f9d1540eb8

关于Flask的典型来源是miguelgrinberg,他写了一些JWT认证教程https://blog.miguelgrinberg.com/post/json-web-tokens-with-public-key-signatures

这是JWT在Flask中的另一个教程:https://realpython.com/token-based-authentication-with-flask/

相关问题 更多 >