跨域造成session丢失

我部署了一个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丢失呢?

阅读 24.8k
4 个回答

所以到现在都没有解决方案么。。

update
我解决了。后端是Java springboot,前端是angular,跨域json通信。
cors方式,配置一个corsfilter,代码如下:

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() {}

}

这个配置在不少地方应该都能找到,不同的主要是两点:
1。response.setHeader("Access-Control-Allow-Credentials","true"); //是否支持cookie跨域
2。response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));

首先,配置了allow-credentials之后,如果allow-origin设为*,跨域时会报错说因为允许credentials,origin不能设为通配*,那所以设为简单的某个domain也是可以的,这种写法应该就是达到了任意domain都可以的效果吧。

然后angular部分也要设定个东西,举个栗子~

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');
      }
    })
  });

恩就是这个$http.get(url, {withCredentials: true})。
ok就酱。

Access-Control-Allow-Origin设置为*只是用来解决post请求跨域的问题的,cookie是没法跨域的,或者说只能跨2级域名,每个cookie都会有对应的域,写的时候可以指定为允许同一个1级域名下的所有2级域名访问,比如sf的sf的cookie图

既然是ng工程,你的载入页面应该只有一个,让java这边给你做一个入口,返回这个页面就好了。

引出的问题可能是你的angular模板如果都需要异步载入,也会跨域,一个方案是像你上面那样加上origin,另一个是直接将模板也打包成脚本直接加入进去

有解决方案了吗?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
1 篇内容引用
宣传栏