request - form - axios vue
Cómo enviar autenticación básica con axios (5)
Hay un parámetro "auth" para la autenticación básica:
auth: {
username: ''janedoe'',
password: ''s00pers3cret''
}
Fuente / Documentos: https://github.com/mzabriskie/axios
Estoy tratando de implementar el siguiente código, pero algo no funciona. Aquí está el código:
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'');
});
Está devolviendo un error 401. Cuando lo hago con Postman hay una opción para configurar la autenticación básica; si no relleno esos campos, también devuelve 401, pero si lo hago, la solicitud es exitosa.
¿Alguna idea de lo que estoy haciendo mal?
Aquí hay parte de los documentos de la API sobre cómo implementar esto:
Este servicio utiliza información de autenticación básica en el encabezado para establecer una sesión de usuario. Las credenciales se validan en el servidor. El uso de este servicio web creará una sesión con las credenciales de usuario pasadas y devolverá un JSESSIONID. Este JSESSIONID se puede usar en las solicitudes posteriores para realizar llamadas de servicio web. *
La razón por la cual el código en su pregunta no se autentica es porque está enviando la autenticación en el objeto de datos, no en la configuración, que lo colocará en los encabezados.
Según los
documentos de axios
, el
alias del método de solicitud
para la
post
es:
axios.post (url [, datos [, config]])
Por lo tanto, para que su código funcione, debe enviar un objeto vacío para datos:
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'');
});
Lo mismo es cierto para usar el parámetro de autenticación mencionado por @luschn. El siguiente código es equivalente, pero utiliza el parámetro auth en su lugar (y también pasa un objeto de datos vacío):
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'');
});
La solución dada por luschn y pillravi funciona bien a menos que reciba un encabezado Strict-Transport-Security en la respuesta.
Agregar withCredentials: true resolverá ese problema.
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'');
});
Por algunas razones, este simple problema está bloqueando a muchos desarrolladores. Luché durante muchas horas con esta cosa simple. Este problema tantas dimensiones:
- CORS (si está utilizando un frontend y backend en diferentes dominios y puertos.
- Configuración de CORS de backend
- Configuración básica de autenticación de Axios
CORS
Mi configuración para el desarrollo es con una aplicación vuejs webpack que se ejecuta en localhost: 8081 y una aplicación de arranque de primavera que se ejecuta en localhost: 8080. Entonces, cuando intento llamar a rest API desde la interfaz, no hay forma de que el navegador me permita recibir una respuesta del backend de primavera sin la configuración CORS adecuada. CORS se puede usar para relajar la protección de Cross Domain Script (XSS) que tienen los navegadores modernos. Según tengo entendido, los navegadores están protegiendo su SPA de un ataque de un XSS. Por supuesto, algunas respuestas en sugirieron agregar un complemento de Chrome para deshabilitar la protección XSS, pero esto realmente funciona Y si lo fuera, solo empujaría el problema inevitable para más adelante.
Configuración de CORS de backend
Así es como debe configurar CORS en su aplicación de arranque de primavera:
Agregue una clase CorsFilter para agregar encabezados adecuados en la respuesta a una solicitud del cliente. Access-Control-Allow-Origin y Access-Control-Allow-Headers son lo más importante para la autenticación básica.
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);
}
...
}
Agregue una clase de configuración que extienda Spring WebSecurityConfigurationAdapter. En esta clase, inyectará su filtro 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());
}
...
}
No tiene que poner nada relacionado con CORS en su controlador.
Interfaz
Ahora, en la interfaz, debe crear su consulta axios con el encabezado Autorización:
<!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>
Espero que esto ayude.
Un ejemplo (axios_example.js) usando Axios en 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);
Asegúrese de que en el directorio de su proyecto haga:
npm init
npm install express
npm install axios
node axios_example.js
Luego puede probar la API REST de Node.js utilizando su navegador en:
http://localhost:5000/search?queryStr=xxxxxxxxx