django - Django+React:对从 React 到 Django 后端的 API 请求正确实施身份验证和安全性的最佳方法是什么
问题描述
我正在做一个Django+React
项目。我的 React 应用程序是我的only UI renderer
(这意味着 Django 不提供模板或任何标记),而我的 Django 应用程序仅用于serving APIs
我访问我的数据库资源。
在一个特定的 React 页面上,我的 Django 后端中有一个向 a 发送请求的按钮login
。test
DRF API
登录 API 视图
class AuthLogin(generics.GenericAPIView):
serializer_class = LoginSerializer
authentication_classes = [SessionAuthentication]
permission_classes = ()
def get(self, request):
user = request.user
if not user and not user.is_authenticated or user.is_anonymous:
return Response(
{
"status": True,
"message": "Login page accessed"
}, status=status.HTTP_200_OK
)
else:
return Response(
{
"status": False,
"message": "You are currently logged in"
}, status=status.HTTP_400_BAD_REQUEST
)
def post(self, request, *args, **kwargs):
res = []
res_stat = status.HTTP_401_UNAUTHORIZED
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=False)
validated_data = serializer.validated_data
if validated_data:
user = dj_auth(username=request.data.get('username'),
password=request.data.get('password'))
if user and user.is_authenticated and not user.is_anonymous:
auth_login(request, user)
res_stat = status.HTTP_200_OK
res = {
"status": True,
"message": "Login successful!",
"login": {
"date_time": timezone.now(),
"user": {
'id': user.id,
'first_name': user.first_name,
'last_name': user.last_name,
'email': user.email,
}
}
}
else:
res_stat = status.HTTP_401_UNAUTHORIZED
res = {
"status": False,
"message": "Invalid username and/or password"
}
else:
res_stat = status.HTTP_401_UNAUTHORIZED
res = {
"status": False,
"message": "Invalid username and/or password"
}
return Response(res, status=res_stat)
测试 API 视图
class Test(APIView):
authentication_classes = [SessionAuthentication]
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
if request.user and request.user.is_authenticated and not request.user.is_anonymous:
return Response({
"test": "coolsss",
"user": request.user.id
}, status=status.HTTP_200_OK)
else:
return Response({
"error": "Mind to login first?"
}, status=status.HTTP_401_UNAUTHORIZED)
到目前为止,在上述 API 上的 Django+React 集成方面做得很好。但是,我注意到了一个安全问题,我不完全确定如何继续前进。
我在隐身浏览器窗口中进行了测试。但是,我也在Postman
. 我注意到的是,在使用相同的csrftoken
和sessionid
cookie 对 Postman 进行测试之前,我已经关闭了我的隐身浏览器。当我关闭浏览器时,我认为会话已被销毁,因为它处于隐身状态。
现在,当我在 Postman 中运行相同的程序时,test
端点仍在进行身份验证、识别用户并返回肯定响应。我不确定这是否应该发生,以及应该使用什么方法来解决这个问题。
我看到这将是一场噩梦的一个示例场景是,Kate 登录并离开她的工作站一分钟。她的同事 John 潜入她的浏览器并窃取了她当前会话csrftoken
的sessionid
cookie 值。
凯特回来了,出于某种原因关闭了她的浏览器。John 在他自己的计算机上使用 Postman 向一个 API 发出了一些 POST 请求,Kate 使用他窃取的令牌和 sessionid 来访问该 API。
由于身份验证中的这个问题session/cookie-based
,我正在考虑实施token-based
身份验证,即使login
视图更适合通过服务器会话和 csrftoken cookie 进行身份验证。
但是,如果我使用基于令牌的,我也会将该令牌存储在本地存储中,以便 React 知道用户仍处于登录状态,并将该令牌用于后续请求。但是话又说回来,极客总是可以使用开发工具并潜入本地存储中的该令牌值。
我非常纠结于如何在后端正确实现身份验证和安全性,同时保持用户登录状态的前端。
解决方案
基于令牌(例如 JWT)是将服务器端服务集成到客户端应用程序的首选选项。至于您面临的问题,最简单的选择是向令牌添加过期选项,这可能仍然不是所有场景的解决方案。
事实是,当您创建客户端应用程序时,客户端拥有控制权,您对此无能为力。保护令牌与保护用户应该考虑的密码相同。您能做的最多就是让其他人更难能够简单地获取令牌并在其他地方使用它。
您可以制作客户端必须生成的具有不同规格的多个令牌,如果所有令牌都匹配,那么您可以为请求提供服务。但同样,这只是让其他人更难复制请求并非不可能。
如果它是一个很难反编译的编译应用程序,并且结合了一些方法,比如使用一些也安全存储在客户端系统中的证书文件,你可以更加确定你的请求的安全性,但是 JS 太简单了阅读和复制。
推荐阅读
- laravel - php artisan storage:链接链接错误的目录
- java - Android比较字符串与数组并删除数组索引值
- angular - 创建模块的 Angular6 服务
- docker - 在 vespa 的同一个容器上部署多个应用程序包
- javascript - Prismic - 如何在不暴露访问令牌的情况下进行 API 调用
- javascript - 从另一个数组中选择同名项目
- sql - SQL Server 参数异常
- angular - url中的多个参数不起作用Angular 6
- python - 使用带有 Pandas 的 Google 表单替代已弃用的方法
- dart - Flutter Await 回调不给出任何响应