我部署了一个angular工程 基于nodejs HTTP-server启动的,登陆url: http://localhost:9000/#/login
java工程项目 登陆url: http://localhost:8060/login
而我现在想在angular工程上完全只是调用java工程项目接口,而java项目现在准备纯碎只是为angular工程提供返回的json数据而已
在过程中出现跨域问题,我就在java工程上统一设置拦截器 在有新请求调用时都设置响应头:
response.setHeader("Access-Control-Allow-Origin" , "*" ); 即可解决跨域问题;
但是session丢失问题没解决
就是说我在angular项目调用登陆接口登陆,服务器端会创建一个session,并返回用户信息及权限信息等json数据 ,还有返回一个jsessionid到客户端;
如图所示:
登陆成功跳转至http://localhost:9000/#/home
但是我在首页点击左侧菜单执行java工程的其他接口时,比如说查询用户列表接口,它又被拦截掉,返回login接口,因为由请求头中找不到对应的jsessionid,相当于当前用户还处于未登陆状态
原理是:每次调用接口即发出新请求首先都会判断url上是否携带jsession,如果没有,则判断请求头的cookies中有jsession,如果已存在,则会传到后台,后台通过jsession获取对应session;可是如果jsession不存在或者通过jsession获取不到对应session的话,则会从新创建一个session
我想问一下就是怎么才能避免跨域调用接口导致session丢失呢?
迷茫2017-05-15 16:54:59
So there is no solution yet. .
update
I solved it. The backend is Java springboot, the frontend is angular, and cross-domain json communication is used.
Cors method, configure a corsfilter, the code is as follows:
package xxxxxx.component;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by skyADMIN on 16/7/4.
*/
@Component
public class CORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
response.setHeader("Access-Control-Allow-Credentials","true"); //是否支持cookie跨域
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
This configuration should be found in many places. The main differences are two points:
1. response.setHeader("Access-Control-Allow-Credentials","true"); //Whether cookies are supported across domains
2. response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
First of all, after configuring allow-credentials, if allow-origin is set to *, an error will be reported when crossing domains, saying that because credentials are allowed, origin cannot be set to wildcard *, so it is also possible to set it to a simple domain. This This writing method should achieve the effect of any domain.
Then the angular part also needs to set something, for example~
angular.module('frontendApp')
.controller('MainCtrl', function ($scope, $http, $location) {
var action = 'islogin';
$http.get(apiUrl + action, {withCredentials: true}).then(function (response) {
console.log(response);
if (response.data === 0) {
$location.url('login');
}
})
});
Well, this is $http.get(url, {withCredentials: true}).
Okay, just sauce.
高洛峰2017-05-15 16:54:59
Access-Control-Allow-Origin is set to * only to solve the problem of cross-domain post requests. Cookies cannot cross domains, or can only cross 2-level domain names. Each cookie will have a corresponding domain, write can be specified to allow access to all second-level domain names under the same first-level domain name, such as sf's
ringa_lee2017-05-15 16:54:59
Since it is an ng project, you should have only one loading page. Just let Java make an entrance for you and return to this page.
The problem may be that if your angular template needs to be loaded asynchronously, it will also cross domain. One solution is to add origin as you did above, and the other is to directly package the template into a script and add it directly