如何使用 axios 发送基本身份验证

How to send Basic Auth with axios

我正在尝试实现以下代码,但有些东西不起作用。这是代码:

      var session_url = 'http://api_address/api/session_endpoint';
      var username = 'user';
      var password = 'password';
      var credentials = btoa(username + ':' + password);
      var basicAuth = 'Basic ' + credentials;
      axios.post(session_url, {
        headers: { 'Authorization': + basicAuth }
      }).then(function(response) {
        console.log('Authenticated');
      }).catch(function(error) {
        console.log('Error on Authentication');
      });

它正在返回 401 错误。当我使用 Postman 时,有一个选项可以设置 Basic Auth;如果我不填写这些字段,它也会 returns 401,但如果我这样做,请求就会成功。

知道我做错了什么吗?

这里是 API 文档的一部分,说明如何实现它:

This service uses Basic Authentication information in the header to establish a user session. Credentials are validated against the Server. Using this web-service will create a session with the user credentials passed and return a JSESSIONID. This JSESSIONID can be used in the subsequent requests to make web-service calls.*

基本验证有一个 "auth" 参数:

auth: {
  username: 'janedoe',
  password: 's00pers3cret'
}

Source/Docs: https://github.com/mzabriskie/axios

示例:

await axios.post(session_url, {}, {
  auth: {
    username: uname,
    password: pass
  }
});

您问题中的代码未进行身份验证的原因是您在数据 object 中发送身份验证,而不是在配置中发送身份验证,后者将把它放在 headers 中。根据 axios docspost 请求方法别名 是:

axios.post(url[, data[, config]])

因此,为了让您的代码正常工作,您需要为数据发送一个空 object:

var session_url = 'http://api_address/api/session_endpoint';
var username = 'user';
var password = 'password';
var basicAuth = 'Basic ' + btoa(username + ':' + password);
axios.post(session_url, {}, {
  headers: { 'Authorization': + basicAuth }
}).then(function(response) {
  console.log('Authenticated');
}).catch(function(error) {
  console.log('Error on Authentication');
});

使用@luschn提到的auth参数也是如此。下面的代码是等效的,但使用 auth 参数代替(并且还传递了一个空数据 object):

var session_url = 'http://api_address/api/session_endpoint';
var uname = 'user';
var pass = 'password';
axios.post(session_url, {}, {
  auth: {
    username: uname,
    password: pass
  }
}).then(function(response) {
  console.log('Authenticated');
}).catch(function(error) {
  console.log('Error on Authentication');
});

在 Node.js 中使用 Axios 的示例 (axios_example.js):

const axios = require('axios');
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;

app.get('/search', function(req, res) {
    let query = req.query.queryStr;
    let url = `https://your.service.org?query=${query}`;

    axios({
        method:'get',
        url,
        auth: {
            username: 'xxxxxxxxxxxxx',
            password: 'xxxxxxxxxxxxx'
        }
    })
    .then(function (response) {
        res.send(JSON.stringify(response.data));
    })
    .catch(function (error) {
        console.log(error);
    });
});

var server = app.listen(port);

请确保在您的项目目录中执行以下操作:

npm init
npm install express
npm install axios
node axios_example.js

然后您可以使用浏览器测试 Node.js REST API:http://localhost:5000/search?queryStr=xxxxxxxxx

参考:https://github.com/axios/axios

由于某些原因,这个简单的问题阻碍了许多开发人员。我为这个简单的事情挣扎了好几个小时。这个问题有多少维度:

  1. CORS(如果您在不同的域和端口上使用前端和后端。
  2. 后端 CORS 配置
  3. Axios 基本认证配置

CORS

我的开发设置是在 localhost:8081 上使用 vuejs webpack 应用程序 运行,在 localhost:8080 上使用 spring 启动应用程序 运行。因此,当尝试从前端调用 rest API 时,如果没有正确的 CORS 设置,浏览器将无法让我从 spring 后端接收响应。 CORS 可用于放宽现代浏览器具有的跨域脚本 (XSS) 保护。据我了解,浏览器正在保护您的 SPA 免受 XSS 攻击。当然,Whosebug 上的一些答案建议添加一个 chrome 插件来禁用 XSS 保护,但这确实有效,如果有效,只会将不可避免的问题推到以后。

后端CORS配置

以下是在 spring 启动应用程序中设置 CORS 的方法:

添加 CorsFilter class 以在对客户端请求的响应中添加适当的 header。 Access-Control-Allow-Origin 和 Access-Control-Allow-Headers 是基本身份验证最重要的东西。

    public class CorsFilter implements Filter {

...
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
        **response.setHeader("Access-Control-Allow-Headers", "authorization, Content-Type");**
        response.setHeader("Access-Control-Max-Age", "3600");

        filterChain.doFilter(servletRequest, servletResponse);

    }
...
}

添加扩展 Spring WebSecurityConfigurationAdapter 的配置 class。在此 class 中,您将注入 CORS 过滤器:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
    @Bean
    CorsFilter corsFilter() {
        CorsFilter filter = new CorsFilter();
        return filter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.addFilterBefore(corsFilter(), SessionManagementFilter.class) //adds your custom CorsFilter
          .csrf()
          .disable()
          .authorizeRequests()
          .antMatchers("/api/login")
          .permitAll()
          .anyRequest()
          .authenticated()
          .and()
          .httpBasic()
          .authenticationEntryPoint(authenticationEntryPoint)
          .and()
          .authenticationProvider(getProvider());
    }
...
}

您不必在控制器中放入任何与 CORS 相关的内容。

前端

现在,在前端,您需要使用授权 header:

创建您的 axios 查询
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
    <p>{{ status }}</p>
</div>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            status: ''
        },
        created: function () {
            this.getBackendResource();
        },
        methods: {
            getBackendResource: function () {
                this.status = 'Loading...';
                var vm = this;
                var user = "aUserName";
                var pass = "aPassword";
                var url = 'http://localhost:8080/api/resource';

                var authorizationBasic = window.btoa(user + ':' + pass);
                var config = {
                    "headers": {
                        "Authorization": "Basic " + authorizationBasic
                    }
                };
                axios.get(url, config)
                    .then(function (response) {
                        vm.status = response.data[0];
                    })
                    .catch(function (error) {
                        vm.status = 'An error occured.' + error;
                    })
            }
        }
    })
</script>
</body>
</html>

希望对您有所帮助。

luschn 和 pillravi 给出的解决方案工作正常,除非您在响应中收到 Strict-Transport-Security header。

添加 withCredentials: true 将解决该问题。

  axios.post(session_url, {
    withCredentials: true,
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/json"
    }
  },{
    auth: {
      username: "USERNAME",
      password: "PASSWORD"
  }}).then(function(response) {
    console.log('Authenticated');
  }).catch(function(error) {
    console.log('Error on Authentication');
  });

如果您尝试进行基本身份验证,可以试试这个:

const username = ''
const password = ''

const token = Buffer.from(`${username}:${password}`, 'utf8').toString('base64')

const url = 'https://...'
const data = {
...
}

axios.post(url, data, {
  headers: {
 'Authorization': `Basic ${token}`
},
})

这对我有用。希望有帮助

您好,您可以通过以下方式做到这一点

    var username = '';
    var password = ''

    const token = `${username}:${password}`;
    const encodedToken = Buffer.from(token).toString('base64');
    const session_url = 'http://api_address/api/session_endpoint';

    var config = {
      method: 'get',
      url: session_url,
      headers: { 'Authorization': 'Basic '+ encodedToken }
    };

    axios(config)
    .then(function (response) {
      console.log(JSON.stringify(response.data));
    })
    .catch(function (error) {
      console.log(error);
    });

我刚遇到这个问题,做了一些研究后我发现数据值必须作为 URLSearchParams 发送,我是这样做的:

getAuthToken: async () => {
const data = new URLSearchParams();
data.append('grant_type', 'client_credentials');
const fetchAuthToken = await axios({
  url: `${PAYMENT_URI}${PAYMENT_GET_TOKEN_PATH}`,
  method: 'POST',
  auth: {
    username: PAYMENT_CLIENT_ID,
    password: PAYMENT_SECRET,
  },
  headers: {
    Accept: 'application/json',
    'Accept-Language': 'en_US',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Access-Control-Allow-Origin': '*',
  },
  data,
  withCredentials: true,
});
return fetchAuthToken;

},

我使用 axios.interceptors.request.use 配置基本身份验证凭据。我有一个带有简单 GET 端点的后端 Springboot(带有 SpringSecurity)应用程序。前端 VueJs 应用程序和后端在不同的端口上运行。

axios.js

import axios from "axios";

const api = axios.create({
  baseURL: "http://api_address",
  timeout: 30000,
});

api.interceptors.request.use(
  async (config) => {
    const basicAuthCredentials = btoa("xxxx" + ":" + "xxxx");
    config.headers.common["Authorization"] = "Basic " + basicAuthCredentials;
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

export default api;

backend.js

import axios from "@/services/axios";

const BackendAPI = {

  listUsers: async () => {
    return axios({
      url: '/users',
      method: 'GET',
      responseType: 'json',
    });
  },
};

export { BackendAPI };

后面是VUE组件Users.vue

...
<script>
import { BackendAPI } from '@/services/backend';

export default {
  name: "Users",
  data() {
    return {
      usersList: [],
    }
  },
  methods: {
    async listUsers() {
      const response = await BackendAPI.listUsers();
      this.usersList = response.data;
    },
  },
};
</script>

后端 spring SecurityConfig.java 使用 httpBasic 作为身份验证并禁用 cors 和 csrf。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/actuator/*")
        .permitAll()
        .anyRequest()
        .authenticated()
        .and()
        .httpBasic()
        .and()
        .cors()
        .disable()
        .csrf()
        .disable();
  }
}
const auth = {
            username : 'test',
            password : 'test'
        }
const response =  await axios.get(yourUrl,{auth}) 

如果您使用基本身份验证,这是可行的