Flask会话未持久



我正在开发一个web应用程序,它使用Flask服务器端和Angular客户端。我需要在这样的应用程序中允许多用户登录,我想使用flask会话对象来处理登录会话,但是会话不会在请求之间持久化,并且每次会话都被销毁。

我已经遵循了一些解决方案(通过在请求和响应中添加特定的头,flask_cors被配置并工作)。

任何建议吗?

谢谢:)编辑:

这是CORS初始化

CORS(app, supports_credentials=True, resources=r'/*')

和我用来填充会话对象的登录方法定义如下:

@app.route('/login', methods=['POST', 'GET'])
def login():
print(request.headers)
_json = request.json
name = _json['username']
password = _json['password']
if name and password:
m = hashlib.md5(password.encode('utf-8')).hexdigest()
results = User.query.filter_by(username=name).first()
if m == results.password:
resp = jsonify("User logged in")
resp.status_code = 200
addRespHeaders(resp)
session.permanent = True
session['username'] = results.username
session['role'] = results.role
session.modified = True
print(session['username'], session['role'])
print(resp.headers)
return resp
else:
resp = jsonify("Attention! Wrong Password")
resp.status_code = 404
addRespHeaders(resp)
return resp
else:
resp = jsonify("Please enter the required fields")
resp.status_code = 404
addRespHeaders(resp)
return resp

最后的addRespHeaders(resp)方法:

def addRespHeaders(resp):
resp.headers.add('Access-Control-Allow-Headers', "Origin, Content-Type, X-Requested-With, Accept, x-auth")
resp.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')

当我调用登录方法并尝试打印session['username']session['role']时,它打印出正确的值,但如果在另一个方法中,如:

@app.route('/user/getLoggedIn', methods=['GET'])
def getLoggedInUser():
print('username' in session)
logged_data = UserPersistence.query.all()[0].username
logged_user = User.query.filter_by(username=logged_data).first()
schema = UserSchema()
resp = jsonify(schema.dump(logged_user))
resp.status_code = 200
addRespHeaders(resp)
return resp

print('username' in session)返回False

Edit2:

我的服务执行请求是这样的:

const httpOptions = {
withCredentials: true,
headers: new HttpHeaders({'Content-Type': 'application/json'})
};
@Injectable({providedIn: 'root'})
export class UserService{
private userUrl = "http://192.168.0.88:5000";
constructor(private http: HttpClient){ }
/** GET users from server */
getUsers(): Observable<User[]>{
return this.http.get<User[]>(this.userUrl + '/users');
}
/** GET user by id. Will 404 if not found */
getUser(id: number): Observable<any>{
const url = `${this.userUrl}/user/${id}`;
return this.http.get<User>(url);
}
getLoggedInUser(): Observable<User>{
const url= `${this.userUrl}/user/getLoggedIn`;
return this.http.get<User>(url);
}
/** POST: login user */
login(username: string, password: string) {
return this.http.post(this.userUrl + '/login', JSON.stringify({"username": username, "password": password}), httpOptions);
}
/** POST: logout logged in user */
logout() {
return this.http.post(this.userUrl + '/logout', httpOptions);
}
/** POST: add a new user to the server */
addUser(user: User) {
return this.http.post(this.userUrl + '/user/add', user, httpOptions);
}
/** PUT: update the user on the server */
updateUser(user: User): Observable<any> {
return this.http.put(this.userUrl + '/user/update', user, httpOptions);
}
/** PUT: update user password */
updatePassword(user: PasswordReset): Observable<any> {
return this.http.put(this.userUrl + '/user/changePassword', user, httpOptions);
}
/** DELETE: delete the user from the server */
deleteUser(user: User | number) {
const id = typeof user == 'number' ? user : user.id;
const url = `${this.userUrl}/user/delete/${id}`;
return this.http.delete(url, httpOptions);
}
}

据我所知,withCredentials: true应该包括凭据。

Edit3:

当我在localhost时,我设法在请求之间持久化会话数据:

session_cookie = SecureCookieSessionInterface().get_signing_serializer(app)
@app.after_request
def after_request(response):
origin = request.headers.get('Origin')
if request.method == 'OPTIONS':
response.headers.add('Access-Control-Allow-Credentials', 'true')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type')
response.headers.add('Access-Control-Allow-Headers', 'x-csrf-token')
response.headers.add('Access-Control-Allow-Methods',
'GET, POST, OPTIONS, PUT, PATCH, DELETE')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
else:
response.headers.add('Access-Control-Allow-Credentials', 'true')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
same_cookie = session_cookie.dumps(dict(session))
response.headers.add("Set-Cookie", f"{same_cookie}; Secure; HttpOnly; SameSite=None; Path=/;")
return response

现在的问题是,如果我尝试在同一网络下的另一台PC上登录,所有请求都被阻止,因为cookie不会在请求之间传递。任何想法?由于

是否添加了support_credentials=True选项初始化扩展?

以下是来自文档的更多内容:

使用cookie使用CORS默认情况下,Flask-CORS不允许跨站点提交cookie,因为它有潜在的安全隐患的影响。如果您希望启用跨站点cookie,您可以这样做添加某种CSRF保护,以确保您和您的用户的安全。

允许cookie或经过身份验证的请求跨源发送,只需将supports_credentials选项设置为True。例如

from flask import Flask, session from flask_cors import CORS

app = Flask(__name__) 
CORS(app, supports_credentials=True)

@app.route("/")
def helloWorld():   
return "Hello, %s" % session['username']

还要检查你的路由是否被列入了CORS使用的白名单,或者路由中是否添加了装饰器。

One of the simplest configurations. Exposes all resources matching /api/* to
CORS and allows the Content-Type header, which is necessary to POST JSON
cross origin.
CORS(app, resources=r'/api/*')

@app.route("/")
def helloWorld():
"""
Since the path '/' does not match the regular expression r'/api/*',
this route does not have CORS headers set.
"""
return '''
<html>
<h1>Hello CORS!</h1>
<h3> End to end editable example with jquery! </h3>
<a class="jsbin-embed" href="http://jsbin.com/zazitas/embed?js,console">JS Bin on jsbin.com</a>
<script src="//static.jsbin.com/js/embed.min.js?3.35.12"></script>
</html>
'''
@app.route("/api/v1/users/")
def list_users():
"""
Since the path matches the regular expression r'/api/*', this resource
automatically has CORS headers set. The expected result is as follows:
$ curl --include -X GET http://127.0.0.1:5000/api/v1/users/ 
--header Origin:www.examplesite.com
HTTP/1.0 200 OK
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Origin: *
Content-Length: 21
Content-Type: application/json
Date: Sat, 09 Aug 2014 00:26:41 GMT
Server: Werkzeug/0.9.4 Python/2.7.8
{
"success": true
}
"""
return jsonify(user="joe")

另外,如果您正在使用蓝图,请记住将蓝图注册到CORS。

Flask-CORS支持开箱即用的蓝图只需传递一个蓝图实例到CORS扩展,一切都会正常工作。

api_v1 = Blueprint('API_v1', __name__)
CORS(api_v1) # enable CORS on the API_v1 blue print

所有示例来自Flask-Cors文档。链接到docs

最新更新