Python 未在浏览器中设置身份验证登录Cookies-Flask后端API+;角7前端
我正在使用一个有角度前端的Flask后端api构建一个Web应用程序。API在上运行,前端在上运行 由于某些原因,浏览器中未设置Cookie。浏览器标题似乎是正确的,但在检查chrome devtools-->应用程序-->存储-->Cookies时,我看不到设置了任何cookie 我错过了什么 相关部分:Python 未在浏览器中设置身份验证登录Cookies-Flask后端API+;角7前端,python,angular,flask,angular-httpclient,flask-jwt-extended,Python,Angular,Flask,Angular Httpclient,Flask Jwt Extended,我正在使用一个有角度前端的Flask后端api构建一个Web应用程序。API在上运行,前端在上运行 由于某些原因,浏览器中未设置Cookie。浏览器标题似乎是正确的,但在检查chrome devtools-->应用程序-->存储-->Cookies时,我看不到设置了任何cookie 我错过了什么 相关部分: from octowc.web_app.resources import ( Test, Refresh, Login, Logout ) from flask import
from octowc.web_app.resources import (
Test, Refresh, Login,
Logout
)
from flask import (
Flask, render_template
)
from flask_jwt_extended import JWTManager
from flask_sqlalchemy import SQLAlchemy, sqlalchemy
from octowc.config import Config
from flask_cors import CORS
from flask_restful import Api
app = Flask(__name__)
api = Api(app)
jwt = JWTManager(app)
CORS(app, origins=['http://localhost:4200']
# JWT token configuration
app.config['JWT_SECRET_KEY'] = conf.jwt_secret_key
app.config['JWT_TOKEN_LOCATION'] = ['cookies']
app.config['JWT_ACCESS_COOKIE_PATH'] = '/api/'
app.config['JWT_REFRESH_COOKIE_PATH'] = '/token'
app.config['JWT_COOKIE_CSRF_PROTECT'] = True
app.config['JWT_COOKIE-DOMAIN'] = 'localhost'
app.config['JWT_COOKIE_SECURE'] = False
app.config['CSRF_IN_COOKIES'] = False
api.add_resource(Refresh, '/token/refresh')
api.add_resource(Test, '/api/test')
api.add_resource(Login, '/login')
api.add_resource(Logout, '/logout')
class Refresh(Resource):
@jwt_refresh_token_required
def post(self):
user = get_jwt_identity()
refresh_token = create_access_token(identity=user)
resp = jsonify({'refresh': True})
set_access_cookies(resp, refresh_token)
return resp
class Test(Resource):
@jwt_required
def get(self):
resp = {'Test': 'Successfull!'}
return resp
@jwt_required
def post(self):
resp = {'Test': 'Successfull!'}
return resp
class Logout(Resource):
def post(self):
resp = jsonify({'Logout:': True})
unset_jwt_cookies(resp)
return resp
class Login(Resource):
parser = reqparse.RequestParser()
parser.add_argument(
'username',
type=str,
required=True
)
parser.add_argument(
'password',
type=str,
required=True
)
def post(self):
try:
data = Login.parser.parse_args()
except BadRequest as _:
return {'Error': 'Bad request'}, 400
username = data['username']
password = data['password']
if username != 'test' or password != 'test':
return {'Error': 'Credentials incorrect'}, 401
access_token = create_access_token(identity=username)
refresh_token = create_refresh_token(identity=username)
resp = jsonify({'Login': True})
set_access_cookies(resp, access_token)
set_refresh_cookies(resp, refresh_token)
return resp
相关角部:
auth.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { map } from 'rxjs/operators';
import { CookieService } from 'ngx-cookie-service';
import { Router } from '@angular/router';
import { environment } from 'src/environments/environment';
import { JwtHelperService } from '@auth0/angular-jwt';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
withCredentials: 'true'
})
};
@Injectable({
providedIn: 'root'
})
export class AuthService {
baseUrl = environment.apiUrl;
jwtHelper = new JwtHelperService();
decodedToken: any;
constructor(
private http: HttpClient,
private cookieService: CookieService,
private router: Router) { }
login(model: any) {
return this.http.post(this.baseUrl + 'login', model, httpOptions);
.pipe(
map((response: any) => {
console.log(response);
}))};
logOut() {
this.cookieService.deleteAll('/', 'localhost');
}
isLoggedIn() {
const cookie = this.cookieService.get('access_token');
return !!cookie;
}
getCSRFToken(type: string) {
return this.cookieService.get(`csrf_${type}_token`);
}
getCookie(type: string) {
return this.cookieService.get(`${type}_token`);
}
}
Request URL: http://localhost:5000/login
Request Method: POST
Status Code: 200 OK
Remote Address: 127.0.0.1:5000
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Origin: http://localhost:4200
Content-Length: 20
Content-Type: application/json
Date: Sat, 04 May 2019 08:09:48 GMT
Server: Werkzeug/0.15.2 Python/3.7.3
Set-Cookie: access_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTY5NTczODgsIm5iZiI6MTU1Njk1NzM4OCwianRpIjoiMTRhZGFkNjEtMTdjYi00NGMwLTg4NjctNGJiOTZiZmY0OGY2IiwiZXhwIjoxNTU2OTU4Mjg4LCJpZGVudGl0eSI6InRlc3QiLCJmcmVzaCI6ZmFsc2UsInR5cGUiOiJhY2Nlc3MiLCJjc3JmIjoiODFlNjYxZmYtZTcxNy00ZmY0LTkxNGItN2EzZWZjZTE5MmM2In0.TV7K2RXDMQsmmmrsmaFiLv6CwmB-Wg5DIdkWfv3IEMI; HttpOnly; Path=/api/
Set-Cookie: csrf_access_token=81e661ff-e717-4ff4-914b-7a3efce192c6; Path=/
Set-Cookie: refresh_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTY5NTczODgsIm5iZiI6MTU1Njk1NzM4OCwianRpIjoiOGVhNWVjNWItMDg5Ny00ZTA2LWIxYWItYjkxNGVhZjI4MjE2IiwiZXhwIjoxNTU5NTQ5Mzg4LCJpZGVudGl0eSI6InRlc3QiLCJ0eXBlIjoicmVmcmVzaCIsImNzcmYiOiJlYzYyMDBkYi1lNmJkLTQ4MDktOTM5Yi01YWZjMWZiZjBlZjAifQ.1kt9N4DTBGH27eBDiz8fiLAiiWPNiEN9q2ddpgCkMw0; HttpOnly; Path=/token
Set-Cookie: csrf_refresh_token=ec6200db-e6bd-4809-939b-5afc1fbf0ef0; Path=/
Vary: Origin
POST /login HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Content-Length: 37
Accept: application/json, text/plain, */*
Origin: http://localhost:4200
withCredentials: true
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.59
Content-Type: application/json
Referer: http://localhost:4200/login?returnUrl=%2Fhome
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
{username: "test", password: "test"}
password: "test"
username: "test"
浏览器标题
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { map } from 'rxjs/operators';
import { CookieService } from 'ngx-cookie-service';
import { Router } from '@angular/router';
import { environment } from 'src/environments/environment';
import { JwtHelperService } from '@auth0/angular-jwt';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
withCredentials: 'true'
})
};
@Injectable({
providedIn: 'root'
})
export class AuthService {
baseUrl = environment.apiUrl;
jwtHelper = new JwtHelperService();
decodedToken: any;
constructor(
private http: HttpClient,
private cookieService: CookieService,
private router: Router) { }
login(model: any) {
return this.http.post(this.baseUrl + 'login', model, httpOptions);
.pipe(
map((response: any) => {
console.log(response);
}))};
logOut() {
this.cookieService.deleteAll('/', 'localhost');
}
isLoggedIn() {
const cookie = this.cookieService.get('access_token');
return !!cookie;
}
getCSRFToken(type: string) {
return this.cookieService.get(`csrf_${type}_token`);
}
getCookie(type: string) {
return this.cookieService.get(`${type}_token`);
}
}
Request URL: http://localhost:5000/login
Request Method: POST
Status Code: 200 OK
Remote Address: 127.0.0.1:5000
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Origin: http://localhost:4200
Content-Length: 20
Content-Type: application/json
Date: Sat, 04 May 2019 08:09:48 GMT
Server: Werkzeug/0.15.2 Python/3.7.3
Set-Cookie: access_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTY5NTczODgsIm5iZiI6MTU1Njk1NzM4OCwianRpIjoiMTRhZGFkNjEtMTdjYi00NGMwLTg4NjctNGJiOTZiZmY0OGY2IiwiZXhwIjoxNTU2OTU4Mjg4LCJpZGVudGl0eSI6InRlc3QiLCJmcmVzaCI6ZmFsc2UsInR5cGUiOiJhY2Nlc3MiLCJjc3JmIjoiODFlNjYxZmYtZTcxNy00ZmY0LTkxNGItN2EzZWZjZTE5MmM2In0.TV7K2RXDMQsmmmrsmaFiLv6CwmB-Wg5DIdkWfv3IEMI; HttpOnly; Path=/api/
Set-Cookie: csrf_access_token=81e661ff-e717-4ff4-914b-7a3efce192c6; Path=/
Set-Cookie: refresh_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTY5NTczODgsIm5iZiI6MTU1Njk1NzM4OCwianRpIjoiOGVhNWVjNWItMDg5Ny00ZTA2LWIxYWItYjkxNGVhZjI4MjE2IiwiZXhwIjoxNTU5NTQ5Mzg4LCJpZGVudGl0eSI6InRlc3QiLCJ0eXBlIjoicmVmcmVzaCIsImNzcmYiOiJlYzYyMDBkYi1lNmJkLTQ4MDktOTM5Yi01YWZjMWZiZjBlZjAifQ.1kt9N4DTBGH27eBDiz8fiLAiiWPNiEN9q2ddpgCkMw0; HttpOnly; Path=/token
Set-Cookie: csrf_refresh_token=ec6200db-e6bd-4809-939b-5afc1fbf0ef0; Path=/
Vary: Origin
POST /login HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Content-Length: 37
Accept: application/json, text/plain, */*
Origin: http://localhost:4200
withCredentials: true
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.59
Content-Type: application/json
Referer: http://localhost:4200/login?returnUrl=%2Fhome
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
{username: "test", password: "test"}
password: "test"
username: "test"
我认为前端和后端需要由同一主机提供服务 和Cookie工作的端口。我认为有一个网页包代理插件 为了解决这个问题——vimalloc 22小时前 webpack.js.org/configuration/dev server/#devserver proxy–vimalloc 22 几小时前 谢谢你给我指明了正确的方向!设置代理成功了。事实证明,您还可以使用Angular CLI设置一个 谢谢大家!
我认为前端和后端需要由同一主机提供服务 和Cookie工作的端口。我认为有一个网页包代理插件 为了解决这个问题——vimalloc 22小时前 webpack.js.org/configuration/dev server/#devserver proxy–vimalloc 22 几小时前 谢谢你给我指明了正确的方向!设置代理成功了。事实证明,您还可以使用Angular CLI设置一个
谢谢大家! 请尝试通过以下命令在https中为您的应用程序提供服务
ng serve--ssl true
,并检查我认为前端和后端需要从同一主机和端口提供服务,才能使Cookie正常工作。我认为有一个webpack代理插件可以处理这个问题。请尝试通过以下命令使用https为您的应用程序提供服务ng serve--ssl true
,然后检查我认为前端和后端需要从同一主机和端口提供服务,cookie才能工作。我认为有一个网页包代理插件来处理这个问题。