精华内容
下载资源
问答
  • 背景:前端每次发送的ajax都是形成新的会话,本地测试时后端获取sessionId为null **********后端的代码修改请查找其他文章,本文只涉及前端 一、解决前端每次发送的ajax都是形成新的会话 我是用的axios,只需在封装...

    背景:前端每次发送的ajax都是形成新的会话,本地测试时后端获取sessionId为null
    **********后端的代码修改请查找其他文章,本文只涉及前端
    一、解决前端每次发送的ajax都是形成新的会话
    我是用的axios,只需在封装的请求时添加

    axios.defaults.withCredentials=true;
    

    根据自己代码做相应改变就行,请求时添加withCredentials属性,并且值为true。
    withCredentials:true;请求时携带cookie
    二、本地测试时结果发现还是无法成功,后端获取的sessionId为null。
    后端返回cookie

    Set-Cookie: SESSION=NzgyMDdjZDgtNjJhMC00NmNkLTkxNWYtNjE4ZmRkYmFlOWQy; Path=/xxx/;
    

    cookie后面还有一个path=/xxx/ 即后端项目路径,
    只需要在为解决跨域设置代理时
    原代码:

    devServer: {
        proxy: {
          '/dev-api/': {
            target: 'http://baidu.com:8811',
            changOrigin: true,
            pathRewrite: {
              '^/dev-api/': '/'
            }
          }
        }
      }
    

    以/dev-api/开头改为后端返回path开头
    修改后:

    devServer: {
        proxy: {
          '/xxx/': {
            target: 'http://baidu.com:8811',
            changOrigin: true,
            pathRewrite: {
              '^/xxx/': '/'
            }
          }
        }
      }
    
    展开全文
  • vue部署在本地的81端口,springboot部署在本地的80端口.设置了跨域访问来进行开发,但是在登陆成功之后设置session,其他接口来调用session的时候失效,显示null 解决方法 第一步 前端 因为我这里前端使用的axios来进行...

    问题

    vue部署在本地的81端口,springboot部署在本地的80端口.设置了跨域访问来进行开发,但是在登陆成功之后设置session,其他接口来调用session的时候失效,显示null

    解决方法

    第一步 前端
    因为我这里前端使用的axios来进行http请求,所以在axios的页面添加上下面一段代码.

    意思是: 它指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求.

    我理解的意思是:设置为true的时候就算是跨域访问也使用相同的cookie(不一定准确)

    axios.defaults.withCredentials = true;
    

    第二步 后端
    后端需要对响应的header设置信息:
    这里是使用了一个过滤器来做:

    package com.bear.bearspringboot.util;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebFilter(urlPatterns = "/*", filterName = "CORSFilter")
    public class CORSFilter implements Filter {
    
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse resp = (HttpServletResponse) response;
            String origin = req.getHeader("Origin");
            if(origin == null) {
                origin = req.getHeader("Referer");
            }
            resp.setHeader("Access-Control-Allow-Origin", origin);//这里不能写*,*代表接受所有域名访问,如写*则下面一行代码无效。谨记
            resp.setHeader("Access-Control-Allow-Credentials", "true");//true代表允许携带cookie
            //下面这两个也很关键
            resp.setHeader("Access-Control-Allow-Methods", "*");
            resp.setHeader("Access-Control-Allow-Headers", "Content-Type,Access-Token");
    //        resp.setHeader("Access-Control-Expose-Headers", "*");
            chain.doFilter(request,response);
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    

    最后在启动类上面加上@ServletComponentScan即可

    参考:
    https://www.cnblogs.com/zimublog/p/10786110.html

    展开全文
  • vue axios中加上这段代码 axios.defaults.withCredentials = true; 完整代码 axios.interceptors.request.use( config => { config.headers.token = "aaa" config.baseURL = "http://localhost:8081/" axios....

    vue axios中加上这段代码

    axios.defaults.withCredentials = true;
    

    完整代码

    Vue.prototype.$axios = axios;
    axios.defaults.withCredentials = true;
    //全局拦截器,每个请求都会被拦截
    axios.interceptors.request.use( config => {
      config.headers.token = "aaa"
      config.baseURL = "http://localhost:8081/"
      return config;
    })
    
    展开全文
  • cookie是浏览器存储信息的一种方式 服务端可以通过响应浏览器set-cookie标头(header),浏览器接收到这个标头信息后,将以文件形式将cookie信息保存在浏览器客户端的计算机上。之后的请求,浏览器将该域的cookie...

    简单回顾cookie和session

    1. cookie和session都是回话管理的方式
    2. Cookie
      • cookie是浏览器端存储信息的一种方式
      • 服务端可以通过响应浏览器set-cookie标头(header),浏览器接收到这个标头信息后,将以文件形式将cookie信息保存在浏览器客户端的计算机上。之后的请求,浏览器将该域的cookie信息再一并发送给服务端
      • cookie默认的存活期限关闭浏览器后失效,即浏览器在关闭时清除cookie文件信息。我们可以在服务端响应cookie时,设置其存活期限,比如设为一周,这样关闭浏览器后也cookie还在期限内没有被清除,下次请求浏览器就会将其发送给服务端了
    3. Session
      • session的使用是和cookie紧密关联的
      • cookie存储在客户端(浏览器负责记忆),session存储在服务端(在Java中是web容器对象,服务端负责记忆)
      • 每个session对象有一个sessionID,这个ID值还是用cookie方式存储在浏览器,浏览器发送cookie,服务端web容器根据cookie中的sessionID得到对应的session对象,这样就能得到各个浏览器的“会话”信息
      • 正是因为sessionID实际使用的cookie方式存储在客户端,而cookie默认的存活期限是浏览器关闭,所以session的“有效期”即是浏览器关闭

    开发环境

    • JDK8、Maven3.5.3、springboot2.1.6、STS4
    • node10.16、npm6.9、vue2.9、element-ui、axios

    springboot后端提供接口

    • demo 已放置 Gitee
    • 本次 demo 只需要 starter-web pom.xml
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    • 后台接口只提供接口服务,端口8080 application.properties
    server.port=8080
    • 只有一个controller,里面有3个handle,分别是登录、注销和正常请求 TestCtrller.java
    @RestController
    public class TestCtrller extends BaseCtrller{
        //session失效化-for功能测试
        @GetMapping("/invalidateSession")
        public BaseResult invalidateSession(HttpServletRequest request) {
            HttpSession session = request.getSession(false);
            if(session != null && 
                    session.getAttribute(SysConsts.Session_Login_Key)!=null) {
                request.getSession().invalidate();
                getServletContext().log("Session已注销!");
            }
            return new BaseResult(true);
        }
        
        //模拟普通ajax数据请求(待登录拦截的)
        @GetMapping("/hello")
        public BaseResult hello(HttpServletRequest request) {
            getServletContext().log("登录session未失效,继续正常流程!");
            return new BaseResult(true, "登录session未失效,继续正常流程!");
        }
        
        //登录接口
        @PostMapping("/login")
        public BaseResult login(@RequestBody SysUser dto, HttpServletRequest request) {
            //cookie信息 
            Cookie[] cookies = request.getCookies();
            if(null!=cookies && cookies.length>0) {
                for(Cookie c:cookies) {
                    System.out.printf("cookieName-%s, cookieValue-%s, cookieAge-%d%n", c.getName(), c.getValue(), c.getMaxAge());
                }
            }
            
            /**
             * session处理
             */
            //模拟库存数据
            SysUser entity = new SysUser();
            entity.setId(1);
            entity.setPassword("123456");
            entity.setUsername("Richard");
            entity.setNickname("Richard-管理员");
            //验密
            if(entity.getUsername().equals(dto.getUsername()) && entity.getPassword().equals(dto.getPassword())) {
                if(request.getSession(false) != null) {
                    System.out.println("每次登录成功改变SessionID!");
                    request.changeSessionId(); //安全考量,每次登陆成功改变 Session ID,原理:原来的session注销,拷贝其属性建立新的session对象
                }
                //新建/刷新session对象
                HttpSession session = request.getSession();
                System.out.printf("sessionId: %s%n", session.getId());
                session.setAttribute(SysConsts.Session_Login_Key, entity);
                session.setAttribute(SysConsts.Session_UserId, entity.getId());
                session.setAttribute(SysConsts.Session_Username, entity.getUsername());
                session.setAttribute(SysConsts.Session_Nickname, entity.getNickname());
                
                entity.setId(null); //敏感数据不返回前端
                entity.setPassword(null);
                return new BaseResult(entity);
            }
            else {
                return new BaseResult(ErrorEnum.Login_Incorrect);
            }
        }
    }
    • 全局跨域配置和登陆拦截器注册 MyWebMvcConfig.java
    @Configuration
    public class MyWebMvcConfig implements  WebMvcConfigurer{
        //全局跨域配置
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**") //添加映射路径
                    .allowedOrigins("http://localhost:8081") //放行哪些原始域
                    .allowedMethods("*") //放行哪些原始域(请求方式) //"GET","POST", "PUT", "DELETE", "OPTIONS"
                    .allowedHeaders("*") //放行哪些原始域(头部信息)
                    .allowCredentials(true) //是否发送Cookie信息
    //              .exposedHeaders("access-control-allow-headers",
    //                              "access-control-allow-methods",
    //                              "access-control-allow-origin",
    //                              "access-control-max-age",
    //                              "X-Frame-Options") //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
                    .maxAge(1800);
        }
        
        //注册拦截器
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new MyLoginInterceptor())
                    .addPathPatterns("/**")
                    .excludePathPatterns("/login")
                    .excludePathPatterns("/invalidateSession");
                    //.excludePathPatterns("/static/**");
        }
    }
    • 登录拦截器 MyLoginInterceptor.java
    public class MyLoginInterceptor implements HandlerInterceptor{
        @Override
        public boolean preHandle(HttpServletRequest request,
                                 HttpServletResponse response, Object handler) throws Exception {
            request.getServletContext().log("MyLoginInterceptor preHandle");
            
            HttpSession session = request.getSession();
            request.getServletContext().log("sessionID: " + session.getId());
            
            Optional<Object> token = Optional.ofNullable(session.getAttribute(SysConsts.Session_Login_Key));
            if(token.isPresent()) { //not null
                request.getServletContext().log("登录session未失效,继续正常流程!");
            } else {
                request.getServletContext().log(ErrorEnum.Login_Session_Out.msg());
    //          Enumeration<String> enumHeader =  request.getHeaderNames();
    //          while(enumHeader.hasMoreElements()) {
    //              String name = enumHeader.nextElement();
    //              String value = request.getHeader(name);
    //              request.getServletContext().log("headerName: " + name + " headerValue: " + value);
    //          }
                //尚未弄清楚为啥全局异常处理返回的响应中没有跨域需要的header,于是乎强行设置响应header达到目的 XD..
                //希望有答案的伙伴可以留言赐教
                response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
                response.setHeader("Access-Control-Allow-Credentials", "true");
                response.setCharacterEncoding("UTF-8");
                response.setContentType("text/html; charset=utf-8");
    //            PrintWriter writer = response.getWriter();
    //            writer.print(new BaseResult(ErrorEnum.Login_Session_Out));
    //            return false;
                throw new BusinessException(ErrorEnum.Login_Session_Out);
            }
            
            return true;
        }
    }
    • 全局异常处理 MyCtrllerAdvice.java
    @ControllerAdvice(
            basePackages = {"com.**.web.*"}, 
            annotations = {Controller.class, RestController.class})
    public class MyCtrllerAdvice {
        
        //全局异常处理-ajax-json
        @ExceptionHandler(value=Exception.class)
        @ResponseBody
        public BaseResult exceptionForAjax(Exception ex) {
            if(ex instanceof BusinessException) {
                return new BaseResult((BusinessException)ex);
            }else {
                return new BaseResult(ex.getCause()==null?ex.getMessage():ex.getCause().getMessage());
            }
        }
    }
    • 后端项目包结构

      后端项目包结构

    vue-cli(2.x)前端

    • demo 已放置 Gitee
    • 前端项目包结构-标准的 vue-cli

      前端项目包结构
    • 路由设置,登录('/')和首页 router/index.js
    import Vue from 'vue'
    import Router from 'vue-router'
    import Home from '@/components/Home'
    import Login from '@/components/Login'
    
    Vue.use(Router)
    
    export default new Router({
      routes: [
            {
              path: '/',
              name: 'Login',
              component: Login
            },
            {
              path: '/home',
              name: 'Home',
              component: Home
            }
      ]
    })
    • 设置端口为8081(后端则是8080)config/index.js
    module.exports = {
      dev: {
    
        // Paths
        assetsSubDirectory: 'static',
        assetsPublicPath: '/',
        proxyTable: {},
    
        // Various Dev Server settings
        host: 'localhost', // can be overwritten by process.env.HOST
        port: 8081, // can be overwritten by 
        //...
    • 简单的登录和首页组件(完整代码-见demo-Gitte链)
      • 登录

        登录组件效果
      • 登录后首页

        首页组件效果
    • axios ajax请求全局设置、响应和异常处理 src/main.js
    import axios from 'axios'
    axios.defaults.baseURL = 'http://localhost:8080'
    //axios.defaults.timeout = 3000
    axios.defaults.withCredentials = true //请求发送cookie
    
    // 添加请求拦截器
    axios.interceptors.request.use(function (config) {
        // 在发送请求之前做些什么
        console.log('in interceptor, request config: ', config);
        return config;
      }, function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
      });
    
    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
        // 对响应数据做点什么
        console.log('in interceptor, response: ', response);
        if(!response.data.success){
            console.log('errCode:', response.data.errCode, 'errMsg:', response.data.errMsg);
            Message({type:'error',message:response.data.errMsg});
            let code = response.data.errCode;
            if('login02'==code){ //登录session失效
                //window.location.href = '/';
                console.log('before to login, current route path:', router.currentRoute.path);
                router.push({path:'/', query:{redirect:router.currentRoute.path}});
            }
        }
        return response;
      }, function (error) {
        // 对响应错误做点什么
            console.log('in interceptor, error: ', error);
            Message({showClose: true, message: error, type: 'error'});
        return Promise.reject(error);
      });
    • 路由URL跳转拦截(sessionStorage初级版)src/main.js
    //URL跳转(变化)拦截
    router.beforeEach((to, from, next) => { 
        //console.log(to, from, next) //
        if(to.name=='Login'){ //本身就是登录页,就不用验证登录session了
            next()
            return
        }
        if(!sessionStorage.getItem('username')){ //没有登录/登录过期
            next({path:'/', query:{redirect:to.path}})
        }else{
            next()
        }
    })
    • 测试过程

      前端进入即是login页,用户名和密码正确则后端保存登录的Session,前端登录成功跳转home页,点击'功能测试'则是正常json响应(Session有效)。如果在本页中主动将Session失效,再次功能测试则会被拦截,跳转登录页。

    碰到的问题

    • 全局异常处理返回的响应中没有跨域需要的 header
      这里使用的是后端全局跨域配置,所以前端请求都支持跨域。但是当主动将Session失效,点击“功能测试”触发登录Session失效拦截,由全局异常处理块返回的响应中却少了console中提示的响应头:
    XMLHttpRequest cannot load http://localhost:8080/hello. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8081' is therefore not allowed access.
    //PS:查看network可以看到请求是200的,但是前端不能拿到响应

    后端强行塞入指定响应头可以达到目的的(见后端拦截器),这样做不优雅,原因还不知道 XD..
    @20190808 更新
    真正上线,代理转发交给nginx,则不会采用后端配置方式,也就不会有这个问题。

    可以继续的话题(链接坑待填)

    • cookie被清理,sessionID对应的session对象怎么回收?
      暴脾气用户禁掉浏览器cookie?
    • springboot-vue-nginx前后端分离跨域配置
    • axios 辅助配置
    • 过滤器与拦截器
      过滤器是在servlet.service()请求前后拦截,springmvc拦截器则是在handle方法前后拦截,粒度不一样。
    • vue-URL跳转路由拦截,vuex状态管理
    • 集群session与redis

    转载于:https://www.cnblogs.com/noodlerkun/p/11094564.html

    展开全文
  • springboot-vue 小项目 简单搭建一个基于springboot+vue的小项目 首先,将整个项目下载下来,然后在springboot-vue-front项目文件夹里面执行命令: npm install 由于网络原因,可能以上命令会报错,可执行(先安装...
  • 前段日子写过一篇关于SpringBoot+Shiro的简单整合的例子,那个例子并不适用于我们目前的前后端分离开发的趋势。我之前写过一个项目也是用到了Shiro的前后端分离,某度了许久也没找到解决方案,什么去掉shiroFilter....
  • Springboot+vue 前后端分离出现后端校验验证码时出现获取session中的值为null的情况。 最近在写前后端分离的项目时,使用到后端验证码的情况。一般是在前端先get请求获取后端图片,并且将生成的验证存储到session中...
  • SpringBoot2.5解决跨域问题2021年秋季新方法 SpringBoot2.5+Vue前后端分离解决session不一致的问题配置后端 (针对springboot2.5)直接在启动类加一个配置前端的遇到的坑(我是新手)总结一句话:用localhost和...
  • 因为前后端属于不同的域,导致每次ajax请求服务器都会当做新的用户访问,导致session丢失 解决方法: &lt;system.webServer&gt; &lt;httpProtocol&gt; &lt;customHeaders&gt; &lt;...
  • Vue项目和flask框架前后端分离session的坑Vue的项目启动Flask的项目启动前后端分离 Vue的项目启动 一般来说,现在的开发环境都是使用自动化工具进行项目创建和开发。 所以,在测试时,自动化工具会帮我们创建一个...
  • 111
  • 当决定前端与后端代码分开部署时,发现shiro自带的session不起作用了。 然后通过对请求head的分析,然后在网上查找一部分解决方案。 最终就是,登录成功之后,前端接收到后端传回来的sessionId,存入cookie当中。 ...
  • 1、vue工程 前端在vue的main文件全局添加一下代码: import axios from 'axios'; axios.defaults.withCredentials=true; 也可以借鉴此博客自己编写过滤器 ...2、后台添加cors-filter 配置 ...
  • 主要介绍了前后端分离 vue+springboot 跨域 session+cookie失效问题的解决方法,解决过程也很简单 ,需要的朋友可以参考下
  • 跨域的时候无法传递Cookies,所以sessionid每次都不一样。 网上说的设置Origin为同源什么的,试过了都不好使。 通过查资料得知 DefaultCookieSerializer 中 sameSite值默认为Lax 通过百度得知: SameSite-...
  • 3、Vue中axios请求配置 XMLHttpRequest的withCredentials标志设置为true,从而使得Cookies可以随着请求发送。因为这是一个简单的GET请求,所以浏览器不会发送一个“预请求”。但是,如果服务器的响应中,...
  • vue 前后分离。登录后由于session id一直变所以提示没有登录问题 1、后端每个接口请求加: // 解决跨域问题。加header String url= request.getScheme()+"://"+request.getServerName()+":"+request....
  • vue前后端分离 用户注册 登录拦截

    千次阅读 2020-06-28 21:53:12
    也是第一次做vue前后端分离 用户注册 登录拦截。项目已经搭建完成,下面分享一下搭建过程。 前端vue 1.login界面 2.注册页面 3.展示页面 前台页面在element官网组件有详细教程,这里不再赘诉。主要还是后台逻辑的...
  • 最近学习使用vuejs前后端分离,重构一个已有的后台管理系统,遇到了下面这个问题: 实现跨域请求时,每次ajax请求都是新的session,导致无法获取登录信息,所有的请求都被判定为未登陆。 1、 vuejs ajax跨域请求 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,648
精华内容 1,459
关键字:

vue前后端分离session

vue 订阅