Hoy encontré un problema muy difícil: el front-end solicita el back-end sin cookies.
No hay ninguna cookie en el encabezado cuando se realiza la solicitud, es posible que falte algo más
Es un dolor de cabeza, probé muchos métodos, pero aún no puedo funcionar, como los siguientes:
1: Usé axios para solicitar. Muchas personas simplemente agregan la siguiente línea de código para hacerlo, pero no
// 允许携带cookie
axios.defaults.withCredentials=true
2: Luego, además de con Credenciales, alguien agregó algunas otras cosas para tener éxito, de la siguiente manera:
// 设置
axio.withCredentials = true;
axio.defaults.withCredentials = true;
// 或者这样设置
axio.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
axio.defaults.crossDomain = true;
axio.defaults.withCredentials = true; //设置cross跨域 并设置访问权限 允许跨域携带cookie信息
axio.defaults.headers.common['Authorization'] = ''; // 设置请求头为 Authorization
return axio.post(PATH.FINANCE_APL_LIST,data, {withCredentials:true
}).then(res=>{
console.log("OKOKOK2-------------------",res)
return res.data.retObj
})
Pero desafortunadamente, todavía fallé
3: Algunas personas dicen que agregue así, haga una configuración global:
import axios from "axios";
// Create an instance using the config defaults provided by the library
// At this point the timeout config value is `0` as is the default for the library
const axio = axios.create({
headers: {
"Content-Type": "application/json;charset=UTF-8"
}
});
// Override timeout default for the library
// Now all requests using this instance will wait 2.5 seconds before timing out
axio.defaults.timeout = 200000;
axio.defaults.withCredentials = true;
Mismo principio, todavía falló
4: Algunos hermanos dijeron que el back-end también debería estar configurado:
[Access-Control-Allow-Credentials] debe ser verdadero
[Access-Control-Allow-Origin] Establecer que la IP permitida a la que se accede no puede ser [*], entrará en conflicto con Credentials = true
Entonces existen los siguientes controles:
4-1: Solo permita que su propio servidor de aplicaciones para el usuario acceda a:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class CorsInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o)
throws Exception {
// 设置允许多个域名请求
String[] allowDomains = {
"http://localhost:3010"
};
Set<String> allowOrigins = new HashSet<String>(Arrays.asList(allowDomains));
String originHeads = httpServletRequest.getHeader("Origin");
if(allowOrigins.contains(originHeads)){
//设置允许跨域的配置
// 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
httpServletResponse.setHeader("Access-Control-Allow-Origin", originHeads);
}
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Headers",
"Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
httpServletResponse.setHeader("X-Powered-By", "Jetty");
String method = httpServletRequest.getMethod();
System.out.println(method);
if (method.equals("OPTIONS")) {
httpServletResponse.setStatus(200);
return false;
}
return true;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
}
}
4-2: Permitir el acceso de todos los servidores de aplicaciones para el usuario
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class CorsInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o)
throws Exception {
String originHeads = httpServletRequest.getHeader("Origin");
httpServletResponse.setHeader("Access-Control-Allow-Origin", originHeads);
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Headers",
"Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
httpServletResponse.setHeader("X-Powered-By", "Jetty");
String method = httpServletRequest.getMethod();
System.out.println(method);
if (method.equals("OPTIONS")) {
httpServletResponse.setStatus(200);
return false;
}
return true;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
}
}
Lo intenté todo, pero no funcionó.
5: Es mejor pensar y pensar, ¿es un problema de ingeniería inicial?
Entonces se agrega un método de prueba al controlador, porque el backend requiere verificación de permisos
Antes de iniciar sesión en el sistema, abre una nueva ventana para visitar directamente en el navegador, es con cookie:
Acceso directo en el navegador después de iniciar sesión, también con cookies:
Entonces hay una pequeña ceja, resumida de la siguiente manera:
1: No llame a través del proyecto de front-end, acceda directamente desde el navegador, llame al back-end mediante métodos como ajax / axios que no sean el proyecto de front-end, que puede llevar cookies
2: Utilice servicios de front-end locales, use axios, etc. para llamar al back-end, sin cookies
Entonces, compare el servicio local con el servicio implementado en el servidor:
Servicio de front-end local, acceso a back-end, sin cookies:
Sorprenda aquí, servicio front-end del servidor, acceso back-end, con Cookie
Esto puede ser un problema ambiental ,,,
Así que fui a Baidu, Google, y solo encontré uno que era algo similar:
Así que solo puedo pensar por mí mismo, piénselo, recuerde que hay una advertencia [Se muestran los encabezados provisionales] en el encabezado de la solicitud sin la cookie, de la siguiente manera:
Fue otra búsqueda, el siguiente hermano, que dijo bien, aunque no resolvió mi problema:
Pensando en nuestro hermano de front-end, parece haber agregado una configuración, no almacenar en caché los recursos solicitados, e ir al servidor para obtener el último cada vez. ¿Podría ser este el problema? El entorno de desarrollo y el entorno de producción están configurados para tener estrategias inconsistentes. ? Aunque la esperanza es escasa, lo probé
El código clave es el siguiente:
Lo probé varias veces, todavía se ve igual, lo que indica que este no es el problema
Busqué y busqué, busqué y busqué, y de repente recordé que el servidor estaba usando una imagen de Docker. El proyecto anterior usaba Nginx como proxy inverso. Esta debería ser la razón. Encontré dos artículos en Internet y encontré a estos dos hermanos. Así es:
Hermano uno:
1: la solución más simple y grosera
Modifique el directorio del proyecto, agregue una carpeta XXX, coloque los recursos estáticos y los archivos de página que necesita el entorno de desarrollo en la carpeta XXX y cambie la dirección del proyecto de acceso en el entorno de desarrollo a http: // localhost : 8485 / XXX. Obviamente, esta solución tiene fallas. Si la ruta de la cookie cambia, necesitamos cambiar la estructura del directorio del proyecto nuevamente, y es posible que también necesitemos modificar la configuración del paquete web (u otra configuración de empaquetado)
2: el camino del proxy nginx
3: solución webpack-dev-server
La idea clave es la anterior: si desea obtener más información, consulte el enlace: https://segmentfault.com/a/1190000013753896
Hermano dos:
La idea clave es la anterior: si desea saber más, consulte el enlace: https://www.jianshu.com/p/cadab71987d2
Entonces ... estoy aquí por hoy, agregue un servicio de agente mañana e intente, debería resolver el problema
Seguimiento: Efectivamente:
Se agrega un proxy a package.json para proxy de la dirección de backend para resolver el problema
Por supuesto, también puede usar Nginx como un proxy para acceder a la parte delantera y trasera
También es posible usar zuul como un proxy de puerta de enlace, todo el acceso al proyecto, primero vaya a zuul y luego reenvíe al servicio respectivo por zuul,
Todos los planes anteriores están bien, cruce el mar y muestre su magia.