我已在
django-graphene
上成功设置了 aws eb
应用程序,但存在跨域身份验证问题。
登录可以在同一域上运行,但是当尝试从跨域登录时,它不起作用。
使用基于会话的身份验证(Cookie)
我的 django-graphql api 位于类似以下的网址上:http://foo.bar.elasticbeanstalk.com/graphql/
当我从 Insomnia(类似于邮递员)登录时,登录有效。这是我收到的回复
Date: Thu, 28 Nov 2019 06:36:39 GMT
Server: Apache/2.4.41 (Amazon) mod_wsgi/3.5 Python/3.6.8
Vary: Cookie,Origin
X-Frame-Options: SAMEORIGIN
Set-Cookie: csrftoken=1FTnBwp8b3OlVVf1NXZqZtWBoZkA1xh4ihryPtvZeTRZj3od5mHn3tDxFhgFvGl9; expires=Thu, 26 Nov 2020 06:36:39 GMT; Max-Age=31449600; Path=/; SameSite=Lax
Set-Cookie: sessionid=vv9e1o2m92ekwcaq8xhzoedf9uhues4u; expires=Thu, 12 Dec 2019 06:36:39 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax
Content-Length: 190
Content-Type: application/json
在失眠状态下,用户已登录。
在前端我使用
gatsby
和 apollo
。前端当前运行在 http://localhost:3000 上。
这是我的 Apollo 客户:
import ApolloClient from "apollo-boost"
import { fetch } from "isomorphic-fetch"
const client = new ApolloClient({
uri: "http://foo.bar.elasticbeanstalk.com/graphql/",
credentials: "include",
fetch,
})
export default client
当我执行登录突变时,没有设置
sessionid
cookie。也没有csrftoken
。
登录突变响应:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
Connection: Keep-Alive
Content-Length: 271
Content-Type: application/json
Date: Thu, 28 Nov 2019 07:39:06 GMT
Keep-Alive: timeout=5, max=99
Server: Apache/2.4.41 (Amazon) mod_wsgi/3.5 Python/3.6.8
Set-Cookie: csrftoken=tVvu46tHoRlKgYFoj5g2ybJ6bt6OsahqmqQrCMyNjnAJYBfXO0Z7AGD16nUzM4Vn; expires=Thu, 26 Nov 2020 07:39:06 GMT; Max-Age=31449600; Path=/
Set-Cookie: sessionid=qmze273tr6srktooa7t0y2n9vfyt408h; expires=Thu, 12 Dec 2019 07:39:06 GMT; HttpOnly; Max-Age=1209600; Path=/
Vary: Cookie,Origin
X-Frame-Options: SAMEORIGIN
响应中有一个
Set-Cookie
代表 csrftoken
和 sessionid
,但 Application -> Cookies -> http://localhost:3000
下没有 cookie
我的
django-cors-headers
设置是:
SESSION_COOKIE_SAMESITE = None
CSRF_COOKIE_SAMESITE = None
CORS_ORIGIN_WHITELIST = [
'http://localhost:3000',
'http://127.0.0.1:3000'
]
CORS_ALLOW_CREDENTIALS = (
True
)
url.py:
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
urlpatterns = [
path('graphql/', csrf_exempt(GraphQLView.as_view(graphiql=True))),
]
如何才能登录?
OP的问题是django中的CORS_ALLOW_CREDENTIALS设置。该值不应该是元组,而应该是布尔值。
CORS_ALLOW_CREDENTIALS = True
然后应设置以下内容:
有关 corsheaders 包文档页面上这些设置的更多信息:https://pypi.org/project/django-cors-headers/
在 Apollo 客户端配置中,确保添加 credentials 选项,如下所示:
const client = new ApolloClient({
uri: GRAPHQL_ENDPOINT_URL,
cache: new InMemoryCache(),
credentials: 'include'
});
对我来说,通过更改 SESSION_ENGINE 来解决问题
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
到
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
settings.py 中的 SESSION 块现在如下所示
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_AGE = 60*60*24
SESSION_COOKIE_SECURE = True