解决AngularJS向服务端发送数据每次sessionID不同的问题

前端使用AngularJS2框架,Server用java写的,工程师写好了,现在需要增加一个判断用户登录超时的功能。用户登录后,使用如下代码将登录sessionID和时间放到Sessioncache中,实质是一个hashmap,key是sessionID,value是time。

String sessionId = req.getSession().getId();
long time = System.currentTimeMillis();
SessionCache.getInstance().getCache().put(sessionId, time);

使用路由守卫,每次用户进行页面跳转向服务端发起请求时,进行一次check。因为同一用户使用同一个浏览器时,在关闭浏览器之前sessionID是一样的(关于sessionID的解释这个博客写的浅显易懂):

好,session 诞生了,从上面的描述来讲,它就是在一次会话中解决2次HTTP的请求的关联,让它们产生联系,让2两个页面都能读取到找个这个全局的session信息。session信息存在于服务器端,所以也就很好的解决了安全问题。

所以使用sessionID从SessionCache中查询,如果没查到,则跳转到login页面;如果查到了,则获取其value即时间,用当前时间与其做差,如果超过一段时间比如10分钟,则跳转到login页面,没超过则正常跳转。思路是比较清晰的。
我测试的时候,都是在本地测试的,webstorm调试前端,intellij调试后端。但是发现同一用户登录后,页面跳转时向服务端发送请求的sessionID跟登录时的不一样,而且每次都不一样。经过查询,是跨域的问题,解决跨域问题,加一个filter类即可。下面是我的filter类代码:

package com.siemens.ct.smartgrid.auth.controller;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *  Authentication for application
 */
public class AuthenticationFilter implements Filter {

    public FilterConfig config;

    public void init(FilterConfig filterConfig) throws ServletException {
        config = filterConfig;
    }

    // Just for debug with webstorm sending cross domain message
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse rsp= (HttpServletResponse) response;

        rsp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
        rsp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        rsp.setHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS,DELETE");
        rsp.setHeader("Access-Control-Max-Age","3600");
        rsp.setHeader("Access-Control-Allow-Credentials","true");
        rsp.addCookie(new Cookie("JSSESIONID",req.getSession().getId()));
        chain.doFilter(request, rsp);
    }

    public void destroy() {
        this.config = null;
    }
}

这个类本来是为了解决了跨域的问题。为了解决sessionID不一致,参考这篇博客,和这篇文章,在**后端**java程序中,用
rsp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
这一行替换掉了原来的rsp.setHeader("Access-Control-Allow-Origin", '*');
同时增加rsp.setHeader("Access-Control-Allow-Credentials","true");这一行(如果原来没有)。

除了后端外,前端angular提交数据的时候,在httpOption中增加了withCredentials: true

完整的httpOption和提交数据部分:

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type':  'application/json'
  }),
  withCredentials: true
};
this.http.post<boolean>('http://localhost:8080/ecfm/api/auth/check', user, httpOptions);
};

再启动程序调试就会发现都sessionID都一致了。


总结:
后端:在filter类中修改"Access-Control-Allow-Origin",增加rsp.setHeader("Access-Control-Allow-Credentials","true");(如果原来没有)
前端:在httpOption中增加withCredentials属性。

你可能感兴趣的:(解决AngularJS向服务端发送数据每次sessionID不同的问题)