Django + ReactJS。 Httponly cookie 没有保存在 React 端的浏览器中。我还在两边都给了 withcredentials : true
Posted
技术标签:
【中文标题】Django + ReactJS。 Httponly cookie 没有保存在 React 端的浏览器中。我还在两边都给了 withcredentials : true【英文标题】:Django + ReactJS. The Httponly cookie is not saved in the browser at React side. I also gave withcredentials : true at both sideDjango + ReactJS。 Httponly cookie 没有保存在 React 端的浏览器中。我还在两边都给了 withcredentials : true 【发布时间】:2021-03-28 06:50:03 【问题描述】:我使用 django rest_framework_simplejwt 包生成 JWT 令牌并将它们设置在带有 Httponly 标志的可浏览 cookie 中。在 Django 方面它工作得很好,但在反应方面它不能很好地工作。 我阅读了许多与此问题相关的答案,例如this 和this,但他们还没有解决我的问题。 请帮助我理解我错在哪里。
DJANGO 一面
views.py
from rest_framework_simplejwt.views import TokenObtainPairView
from django.conf import settings
from rest_framework import status
from rest_framework_simplejwt.exceptions import TokenError,\
InvalidToken
from rest_framework.response import Response
class MyTokenObtainPairView(TokenObtainPairView):
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except TokenError as e:
raise InvalidToken(e.args[0])
# set access token in browser with Httponly cookie.
res = Response(serializer.validated_data, status=status.HTTP_200_OK)
access_token = serializer.validated_data['access']
res.set_cookie("access_token", access_token, max_age=settings.SIMPLE_JWT.get('ACCESS_TOKEN_LIFETIME').total_seconds(),samesite='Lax',secure=False, httponly=True)
return res
authentication.py
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.conf import settings
class CookieHandlerJWTAuthentication(JWTAuthentication):
def authenticate(self, request):
# If cookie contains access token, put it inside authorization header
access_token = request.COOKIES.get('access_token')
if(access_token):
request.META['HTTP_AUTHORIZATION'] = 'header_type access_token'.format(
header_type=settings.SIMPLE_JWT['AUTH_HEADER_TYPES'][0], access_token=access_token)
return super().authenticate(request)
urls.py
from .views import MyTokenObtainPairView
urlpatterns = [
......
path('auth/', include('djoser.urls')),
# path('auth/', include('djoser.urls.jwt')),
path('auth/api/token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
]
settings.py
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
'http://127.0.0.1:8000'
)
完美运行(使用 Httponly 在 cookie 中设置令牌。):
REACTJS 方面
Login.js
axios.defaults.withCredentials = true
const Login = () =>
const [ivalue, setValue] = useState();
const state, dispatch = useContext(Authcontext);
.......
const loginClick = (e) =>
e.preventDefault();
setLoader(true);
axios.post('http://127.0.0.1:8000/auth/api/token/',
username: ivalue.username,
password: ivalue.password,
)
.then((res) =>
setValue( password: "" );
dispatch(
type: LOGIN_SUCCESS,
);
setLoader(false);
history.push("/my_profile");
)
.catch((err) =>
setLoader(false);
setOpen( act: true, msg: "error" );
dispatch(
type: LOGIN_ERROR,
);
setError(err.response.data);
);
;
.........
;
Myprofile.js
axios.defaults.withCredentials = true
const MyProfile = () =>
const history = useHistory();
const state, dispatch = useContext(Authcontext);
useEffect(() =>
const auth_check = () =>
axios.get('http://127.0.0.1:8000/auth/users/me/')
.then((res) =>
dispatch(
type: AFTER_LOGIN,
payload: res.data
);
)
.catch((err) =>
history.push('/login')
);
;
auth_check();
, []);
.......
JWT 响应(浏览器中未设置 cookie)。
未经授权的错误
【问题讨论】:
您好,我也遇到了同样的问题。我在 React 中获取(和服务)localhost
,但问题仍然存在。
@CoronelV 在这里查看您的问题答案:***.com/a/66952449/14131913
【参考方案1】:
我将后端和前端设置在同一个 IP 下。前任。我的后端是
本地主机:8000
前端是
本地主机:3000
不同的端口相同的IP。
这不是投入生产时您可以拥有任何域的场景。
【讨论】:
【参考方案2】:您在 set-cookie 标头中获得了 samesite=Lax 值,尝试使用 CSRF_COOKIE_SECURE = True, SESSION_COOKIE_SECURE = True, CSRF_COOKIE_SAMESITE = 'None', SESSION_COOKIE_SAMESITE = 'None'
这将让浏览器即使来自不同的域也可以设置 cookie。
并在您的客户端使用withCredentials: true
。
【讨论】:
以上是关于Django + ReactJS。 Httponly cookie 没有保存在 React 端的浏览器中。我还在两边都给了 withcredentials : true的主要内容,如果未能解决你的问题,请参考以下文章
如何解决“未捕获的类型错误:无法读取未定义的属性'参数'”reactjs + django