Ответ 1
Существует параметр "auth" для Basic Auth:
auth: {
username: 'janedoe',
password: 's00pers3cret'
}
Источник/Документы: https://github.com/mzabriskie/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. Когда я делаю это с почтальоном, есть возможность установить Basic Auth; если я не заполняю эти поля, он также возвращает 401, но если я это сделаю, запрос будет успешным.
Есть идеи, что я делаю не так?
Вот часть документов API о том, как реализовать это:
Эта служба использует информацию базовой аутентификации в заголовке для установления сеанса пользователя. Учетные данные проверяются на сервере. Использование этого веб-сервиса создаст сеанс с переданными учетными данными пользователя и вернет JSESSIONID. Этот JSESSIONID может использоваться в последующих запросах для выполнения вызовов веб-службы. *
Существует параметр "auth" для Basic Auth:
auth: {
username: 'janedoe',
password: 's00pers3cret'
}
Источник/Документы: https://github.com/mzabriskie/axios
Причина, по которой код в вашем вопросе не проходит проверку подлинности, заключается в том, что вы отправляете аутентификацию в объекте данных, а не в конфиге, который поместит его в заголовки. Согласно документам axios, псевдоним метода запроса для post
:
axios.post(url [, data [, config]])
Поэтому, чтобы ваш код работал, вам нужно отправить пустой объект для данных:
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');
});
То же самое верно для использования параметра auth, упомянутого @luschn. Следующий код эквивалентен, но использует вместо этого параметр auth (а также передает пустой объект данных):
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');
});
По некоторым причинам эта простая проблема блокирует многих разработчиков. Я много часов боролся с этой простой вещью. Эта проблема как много измерений:
CORS
Моя установка для разработки выполняется с помощью приложения vuejs webpack, работающего на localhost: 8081, и приложения весенней загрузки, работающего на localhost: 8080. Поэтому при попытке вызвать rest API из внешнего интерфейса браузер не позволит мне получить ответ от весеннего бэкэнда без надлежащих настроек CORS. CORS можно использовать для ослабления защиты кросс-доменных скриптов (XSS), которую имеют современные браузеры. Насколько я понимаю, браузеры защищают ваш SPA от атаки XSS. Конечно, в некоторых ответах на StackOverflow предлагалось добавить плагин chrome для отключения защиты XSS, но это действительно работает И если бы это было так, это только подтолкнуло бы неизбежную проблему на потом.
Конфигурация серверной части CORS
Вот как вы должны настроить CORS в своем весеннем загрузочном приложении:
Добавьте класс CorsFilter, чтобы добавить правильные заголовки в ответ на запрос клиента. 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. В этом классе вы внедрите свой фильтр 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 в ваш контроллер.
Внешний интерфейс
Теперь во внешнем интерфейсе вам нужно создать свой запрос axios с заголовком Authorization:
<!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.
Добавление 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');
});
Пример (axios_example.js) с использованием Axios в Node.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
Затем вы можете протестировать API REST Node.js, используя свой браузер по адресу: http://localhost:5000/search?queryStr=xxxxxxxxx
Ссылка: https://github.com/axios/axios