zoukankan      html  css  js  c++  java
  • djangorestframework+vue-cli+axios,为axios添加token作为headers踩坑记

    情况是这样的,项目用的restful规范,后端用的django+djangorestframework,前端用的vue-cli框架+webpack,前端与后端交互用的axios,然后再用户登录之后,axios添加token作为axios的header并请求后端,后端部分用的djangorestframework的认证组件。

    以上的相关知识,不是本篇文章的重点,请移步:

    前后端分离djangorestframework——认证组件

    vue(9)—— 组件化开发 - webpack(3)

    vue(6)—— vue中向后端异步请求

    postman测试

    在最开始写好后端

    认证组件:

    视图部分装饰认证组件:

    vue部分,做了个判断,如果用户是登录状态,自动设置默认的headers:

    添加了请求拦截器之后,前端会自动对每个请求之前请求一次,请求方式为OPTIONS,之后再发出真实的请求

    关于这个为什么会做两次请求是因为:

    浏览器会对复杂请求进行处理,在发送真正的请求前, 会先发送一个方法为OPTIONS的预请求(preflight request), 用于试探服务端是否能接受真正的请求,如果options获得的回应是拒绝性质的,比如404403500等http状态,就会停止post、put等请求的发出

    有三种方式会导致这种现象:

    • 请求方法不是GET/HEAD/POST。即复杂请求
    • POST请求的Content-Type并非application/x-www-form-urlencoded, multipart/form-data, 或text/plain。最常见的json就不是
    • 请求设置了自定义的header字段。我这里就设置了token作为自定义的headers

    用的postman做的测试:

    返回结果:

    项目真实测试 

    然后在项目真实测试的时候:

    前端用的vue-cli +webpack,启动项目,并抓包查看时,请求状态500

    并且请求的参数并没有给上header

    后端就是报错:

     就是这个:

    TypeError: cannot unpack non-iterable AuthenticationFailed object

    并且前端的console部分还报同源策略的错:

    我跟你说,你要是跑去后端设置中间件的response的话,你就距离正确答案越来越远了,我的中间件部分是这样的:

    然后根据前面用postman测试都没问题,所以我判定,一定不是中间件的问题

    思来想去,根本的原因就是拿不到token,所以我开始在这方面思考,然后我注释了那段是否带有token的判断,再测试:

    打印request.META

    注释掉验证部分,只是打印看看request.META里的数据

    前端再次请求:

    OPTIONS请求方式因为已经取消了验证所以不报错了:

    第二次真实请求也出现了,并且返回状态码200

     header部分也带上了token:

     

    也就是说,前端装饰上了token的,但是后端没有拿到,所以报错了

    最后看看,后端print(request.META)

    因为有两次请求,看看两次到底有什么不同(我已经删除掉了一些无关精要的数据)

    第一次请求时:

    {'ALLUSERSPROFILE':'RUN_MAIN': 'true', 'SERVER_NAME': 'www.xmind.net', 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8000', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'OPTIONS', 'PATH_INFO': '/api/v1/', 'QUERY_STRING': '', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'text/plain', 'HTTP_HOST': '127.0.0.1:8000', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_ACCESS_CONTROL_REQUEST_METHOD': 'GET', 'HTTP_ORIGIN': 'http://localhost:8080', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3738.0 Safari/537.36 Edg/75.0.107.0', 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS': 'authorization', 'HTTP_ACCEPT': '*/*', 'HTTP_REFERER': 'http://localhost:8080/Course', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7', 'wsgi.input': <_io.BufferedReader name=628>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>}

    第二次请求时:

    {'ALLUSERSPROFILE': 'RUN_MAIN': 'true', 'SERVER_NAME': 'www.xmind.net', 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8000', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/api/v1/', 'QUERY_STRING': '', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'text/plain', 'HTTP_HOST': '127.0.0.1:8000', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_ACCEPT': 'application/json, text/plain, */*', 'HTTP_ORIGIN': 'http://localhost:8080', 'HTTP_AUTHORIZATION': '626d34f7-2302-4bb0-a012-5daf0f588d8c', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3738.0 Safari/537.36 Edg/75.0.107.0', 'HTTP_REFERER': 'http://localhost:8080/Course', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7', 'wsgi.input': <_io.BufferedReader name=632>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>}

    发现前面一大段都相同,就从请求方式开始有不同的,所以我重新设置了认证组件。

    因为一个请求方式是OPTIONS,一个是GET,并且看前端部分,当请求方式是OPTIONS的时候因为是浏览器自动发的预请求,所以没有按我们设定的带上自定义的header,也就没有Authorization-token这个参数了

    终于发现了问题所在,最后在后端做了个判断,当请求方式是OPTIONS的时候,跳过验证,然后完美解决:

    前端请求:没问题,都是200

    并且后端确实可以打印出对应的用户名和token:

    好的,踩坑完毕,感谢查看

  • 相关阅读:
    poj 1328 Radar Installation (贪心)
    hdu 2037 今年暑假不AC (贪心)
    poj 2965 The Pilots Brothers' refrigerator (dfs)
    poj 1753 Flip Game (dfs)
    hdu 2838 Cow Sorting (树状数组)
    hdu 1058 Humble Numbers (DP)
    hdu 1069 Monkey and Banana (DP)
    hdu 1087 Super Jumping! Jumping! Jumping! (DP)
    必须知道的.NET FrameWork
    使用记事本+CSC编译程序
  • 原文地址:https://www.cnblogs.com/Eeyhan/p/10711144.html
Copyright © 2011-2022 走看看