skyADMIN

angular + springboot 以CORS方式跨域并解决cookie/session问题

上篇文章已经说了一个简单的查询应用,get请求,给服务器配cors就可以了,但是cookie发不过去,所以呢,会被卡在一个尴尬的位置——登陆,唔,说得高大上点叫认证之类的,查资料发现跨域掉session看上去好像是不可解的问题。

然后有人放了这个链接:https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/

不带超链接了,万一以后失效呢,这是一家公司,做的产品好像就是一种基于token的认证方式的什么auth0。整片文章的大意呢就是对比基于cookie的认证和基于token的认证的优缺点。有兴趣自己看,因为不打算用这种模式,所以不多说。

虽然cookie是浏览器弄出来的一坨shit,但这种方法简单啊,传统啊。毕竟学校开发团队,一上来门槛太高不利于后续成员培养。所以我找了几天看看能不能想办法还是能跨域传递cookie,其间也有人跟我说可以让前端用node来渲染,因为跨域是浏览器为了安全做的限制,node是在服务器端的,并没有这个限制,想想其实也有道理,但是这个部分技术栈积累太少了,还是最后再考虑吧。

几天时间翻了无数中文英文教程,从stackoverflow到github到乱七八糟的论坛,还有诸如csdn,百度知道之类的地方,都找过了,主要还是英文不够好,这类问题在中文里搜找出来的全是shit。

首先CORS跨域资源共享,要在后端设定一些东西,后端我用的Java springboot,代码如下:

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

}

关键行是支持跨域true,和跨域源,因为要支持cookie跨域就不能用*作通配,甚至,两个也不行,开发者工具控制台会输出:XMLHttpRequest cannot load http://xxxxxxxx:8081/login?username=123&password=456. The ‘Access-Control-Allow-Origin’ header contains multiple values ‘http://localhost:9000,http://localhost:9001’, but only one is allowed. Origin ‘http://localhost:9001’ is therefore not allowed access.

后端设置完毕后前端也需要改一些地方:

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

get参数里不光带个url,可选的option需要加上{withCredentials: true}。好了,世界和平了。唔,我还得想想能不能把请求地址限定在本地和指定的domain,提高提高安全性。

码字很辛苦,转载请注明来自环宇博客《angular + springboot 以CORS方式跨域并解决cookie/session问题》

评论