在javascript和axios中为来自前端的每个api调用发送firebase身份验证令牌

Posted

技术标签:

【中文标题】在javascript和axios中为来自前端的每个api调用发送firebase身份验证令牌【英文标题】:send firebase authentication token for every api call from frontend in javascript and axios 【发布时间】:2021-06-02 17:48:19 【问题描述】:

我正在构建一个使用 firebase 身份验证的网络应用程序。我正在尝试将 firebase 令牌发送到每次调用的后端 API。 我可以检索令牌并将其打印在控制台中,但是每当我尝试将其发送到后端时,令牌似乎都是空的。 我使用的后端是 Python django,

这是我尝试过的,

token.js

function clienttoken()
    
        firebase.auth().onAuthStateChanged(function myuser(user) 
        if (user) 

    //window.location.href = 'index.html';
    firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) 
  // Send token to your backend via HTTPS
        var token = idToken;
        window.alert(token);
        //return token;
  )
        );
  

我能够在控制台中成功打印令牌。

当我尝试在 index.html 中使用它时

<script>
      (function () 
        var output = document.getElementById('output');
        document.getElementById('post').onclick = function mydata () 
          var data = document.getElementById('data').value;
          
          
          var token =  clienttoken();
          
          //window.alert(token);

            
            const config = 
                headers:  Authorization: 'Bearer' +token  
            ; 
            
          axios.post('http://127.0.0.1:7000/posts/', mydata.data,config)
            .then(function (res) 
              //output.className = 'container-fluid';
                resp = JSON.stringify(res.data.body);
                resp_new=resp.replace(/\\n/g,'\n')
              //output.innerHTML = JSON.stringify(res.data.body);
              $("#resp").text(resp_new);
              $("#resp").show()
            )
            .catch(function (err) 
              output.className = 'container text-danger';
              output.innerHTML = err.message;
            ); 
        ;
      )(); 
    </script>

Axios 甚至在获取令牌之前就开始执行,并且每次都会向后端发送一个空令牌。

我尝试使用异步功能 token.js

 async function retrievetoken()
            
            
        firebase.auth().onAuthStateChanged(async function mytoken(user) 
          if (user) 
            // User is signed in.
            
            
            const idtoken =  await firebase.auth().currentUser.getIdToken(/* forceRefresh */ true)
                        
                //window.alert(token);
                return idtoken;
          
            
           else 
            // No user is signed in.
            
            window.location.href = 'login.html';
          
        );

index.html

 <script>
          (function () 
            var output = document.getElementById('output');
            document.getElementById('post').onclick = function mydata () 
              var data = document.getElementById('data').value;
              
              async function retrievetoken()
              const token = await clienttoken();
              
              window.alert(token);
                ;
          )(); 
        </script>

我试图打印令牌,但我得到的只是[Object:Promise]。即使在异步调用之后,也会将空令牌发送到后端。

请帮助我了解如何为每个 API 调用发送 firebase 令牌。

还请找到我的后端编码,

class GetPostList(APIView):
    cred = credentials.Certificate(r'pathto/firebase-sdk.json')

    firebase_admin.initialize_app(cred)
    
    def post(self,request,format=None):
        
        
        jwt_token = request.META.get('Authorization')

        #jwt_token = request.headers['Authorization']

        decoded_token = auth.verify_id_token(jwt_token)
        uid = decoded_token['uid']


        endpoint = "https://jsonplaceholder.typicode.com/posts/"
        header = "Content-type": "application/json;charset=UTF-8"
        send_data = request.data

        if uid is not None:  
            response = requests.post(endpoint, json=send_data, headers=header)
            return Response(response.json())
        else:

            return Response('error': 'Token does not exist', status=401)

我认为我确信后端编码看起来不错。但是,我无法从前端为每个 API 调用发送令牌。

【问题讨论】:

为什么要把token 用大括号括起来? (这里: const config = headers: Authorization: 'Bearer' +token ; ) 【参考方案1】:

使用回调函数时,return 关键字返回的是回调函数,而不是原始函数。因此,您需要使用 await 关键字来等待 promise 解析,然后返回该值。

为避免这种情况,您应该使用firebase.auth().currentUser 来获取当前用户,而不是为用户登录或注销创建监听器。这还有一个好处,即您的函数不会在用户注销时重新运行等。

 async function retrieveToken() 
    const currentUser = firebase.auth().currentUser;
    if (user) 
            // User is signed in.
            const idToken = await firebase.auth().currentUser.getIdToken( /* forceRefresh */ true)
            // Because this return statement is no longer in a nested callback function, it now returns properly.
            return idtoken;
         else 
            // No user is signed in.
            window.location.href = 'login.html';
        
 

【讨论】:

以上是关于在javascript和axios中为来自前端的每个api调用发送firebase身份验证令牌的主要内容,如果未能解决你的问题,请参考以下文章

数据未使用 axios 渲染/console.log,使用来自 mongoDB 的数据

React Redux Axios:POST 请求未收到来自 redux 状态的凭据

反应应用程序中来自axios POST的空响应,rails服务器显示201状态

ReactJS/Express Axios POST 返回 404,来自 Postman

使用 Axios 上传文件时出现 JavaScript CORS 错误

在 Nuxt JS 中为 Axios 配置本地 php 端点