精华内容
下载资源
问答
  • springboot集成spring-sessionspring-redis实现session共享说明一.流程图1.普通集成2.多模式redis情况下的集成二.普通spring-session集成redis1.引入jar包2.创建springsession,springredis配置类3.配置类中的关键...

    说明

    本文提到的集成是基于springboot,及非官方提供的redis配置方式的情况下集成(如,官方在yml文件中配置的redis相关的key类似spring.redis.host,但是我们项目中提供的redis配置可能不是这种官方配置,如,我的项目用到的redis配置类似于redis.master.host这样的.而这样配置,spring是解析不到的,就需要我们手动提供给spring-redis).此外,当我们需要用到多种模式的redis时,也适用.如果您只是集成一种模式的redis,且,redis的配置是官方的配置,那么,可以查找更加简洁的集成方式.

    一.流程图

    1.普通集成

    1.引入jar包
    2.创建配置类,开启注解扫描
    3.配置redis工厂类
    4.继承AbstractHttpSessionApplicationInitializer
    5.启动测试通过
    开始集成
    spring-session,spring-redis
    EnableRedisHttpSession注解开启
    在配置类中配置redis工厂类
    注入自定义的配置类
    集成完毕
    普通集成

    2.多模式redis情况下的集成

    1.引入jar包
    2.自定义RedisSessionRepository
    3.复制一份RedisSessionMapper
    4.自定义config类
    5.自定义的config类中实现多模式的RedisOperations
    6.启动测试通过
    开始集成
    spring-session,spring-redis
    实现集合形式的RedisOperations 及操作
    放在同级下,供自定义的类调用
    核心是EnableSpringHttpSession注解开启
    提供给自定义的Repository类
    集成完毕
    普通集成

    二.普通spring-session集成redis

    1.引入jar包

    这里用的是spring对应的包

    <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-redis</artifactId>  
    </dependency>  
    <dependency>  
            <groupId>org.springframework.session</groupId>  
            <artifactId>spring-session-data-redis</artifactId>  
    </dependency>  
    

    2.创建springsession,springredis配置类

    @Configuration
    @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
    public class SpringRedisSessionConfig{
    

    @Configuration注解不用多解释.@EnableRedisHttpSession注解是开启springsession,我们用的session都将是被spring所管理的session了,同时,这个注解也指明了,用什么容器存储session信息,也就是redis.里面的maxInactiveIntervalInSeconds配置是设置session的最大存活时间,默认是1800秒.强调的是,这个存活时间,也是我们session在redis中存的值的过期时间.

    3.配置类中的关键bean维护

    虽然我们在SpringRedisSessionConfig这个自定义的配置类上打了注解,但是我们还没有提供给spring-redis一个db的连接也好,通道也好,那么我们这里需要在该类里给定这个通道或者连接.

    因为redis有三种模式-standalone,sentinel,cluster,所以这里,我们可提供给spring-redis的通道应该有三种.集成的时候选择一种实现即可,不能同时提供三种,因为spring-redis只需要唯一的一个连接方式或者通道.

    3.1.standalone模式的通道提供

    @Bean("redisStandaloneConnectionFactory")
        public RedisConnectionFactory redisStandaloneMasterConnectionFactory() {
            RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration("127.0.0.1", 6379);
            RedisConnectionFactory lettuceConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration);
            return lettuceConnectionFactory;
        }
    

    3.2.sentinel模式的通道提供

    @Bean("redisSentinelctionFactory")
        public RedisConnectionFactory redisSentinelctionFactory() {
            RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration()
                    .master("mymaster")
                    .sentinel("10.70.33.238", 26379)
                    .sentinel("10.70.33.239", 26379)
                    .sentinel("10.70.33.246", 26379);
            return new JedisConnectionFactory(redisSentinelConfiguration);
        }
    

    3.3.cluster模式的通道提供

    @Bean("redisRedisClusterFactory")
        public RedisConnectionFactory redisSentinelctionFactory() {
            RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration()
            RedisNode redisNode1 = new RedisNode("127.0.0.1", 6379);
            RedisNode redisNode2 = new RedisNode("127.0.0.1", 6379);
            redisClusterConfiguration.addClusterNode(redisNode1);
            redisClusterConfiguration.addClusterNode(redisNode2);
            return new JedisConnectionFactory(redisClusterConfiguration);
        }
    

    至此,三种模式redis的配置已经提供给spring-redis管理.

    4.将自定义配置SpringRedisSessionConfig注册给spring的AbstractHttpSessionApplicationInitializer管理

    /**
     * 为了使每个serverlet容器都使用 spring 提供的 springSessionRepositoryFilter 过滤器创建此类.
     * 上述过滤器,作用是用Spring会话支持的自定义实现替换HttpSession
     * @author 愉快淡定
     */
    public class ForSpringSessionRepositoryFilter extends AbstractHttpSessionApplicationInitializer {
    
    
        public ForSpringSessionRepositoryFilter() {
            super(SpringRedisSessionConfig.class);
        }
    
    }
    

    实现方式比较简单,直接继承后,通过构注册.

    5.启动测试

    经过上述操作,普通的或者说单模式redis情况下的spring-session集成redis已经完成.

    测试是否共享,我这里用到了nginx,用它进行负载均衡代理,请求我的两个端口下的项目,同时两个端口下的项目打印进来的请求的sessionId进行对比.

    nginx配置:

    upstream springboot{
    		server 127.0.0.1:8090 weight=1;
    		server 127.0.0.1:8091 weight=2;
        }
    	server {
            listen       8089;
            server_name  localhost;
    
            #charset koi8-r;
    
            #access_log  logs/host.access.log  main;
    
            location / {
                proxy_pass   http://springboot;
                index  index.html index.htm;
            }
    
            #error_page  404              /404.html;
    
            # redirect server error pages to the static page /50x.html
            #
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
    
            # proxy the PHP scripts to Apache listening on 127.0.0.1:80
            #
            #location ~ \.php$ {
            #    proxy_pass   http://127.0.0.1;
            #}
    
            # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
            #
            #location ~ \.php$ {
            #    root           html;
            #    fastcgi_pass   127.0.0.1:9000;
            #    fastcgi_index  index.php;
            #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #    include        fastcgi_params;
            #}
    
            # deny access to .htaccess files, if Apache's document root
            # concurs with nginx's one
            #
            #location ~ /\.ht {
            #    deny  all;
            #}
        }
    

    实现代理后,发起请求,对比sessionId,正常情况下,两个端口下打印出来的sessionId应该是一致的.

    我们还需要到redis中确认,是不是按我们的预期,session的信心存进了redis中.存在spring中的key是spring:session:接后续内容的模式,如图:

    img

    三.集成多种类型redis(standalone,sentinel,cluster)

    说明里我已经提到了,因为我的redis在yml文件中配置是非官方那样的,且,我的这边需求,集成多种模式的redis来存储session信息,就需要利用以下方式来集成.

    其实我们这次集成的核心是围绕@EnableSpringHttpSession及重写适合自己的RedisSessionRepository类来展开的.

    翻开RedisSessionRepository的源码,我们发现,spring-redis仅提供了单一的redis操作对象来进行数据的操作,进而限制了我们只能集成一种模式的redis.源码片段如下:

    public class RedisSessionRepository implements SessionRepository<RedisSessionRepository.RedisSession> {
        private static final String DEFAULT_KEY_NAMESPACE = "spring:session:";
        private final RedisOperations<String, Object> sessionRedisOperations;
        private Duration defaultMaxInactiveInterval = Duration.ofSeconds(1800L);
    
    public void deleteById(String sessionId) {
            String key = this.getSessionKey(sessionId);
            this.sessionRedisOperations.delete(key);
        }
    

    我们看到上面的源码中,RedisOperations<String, Object>操作对象只有一个,对应的,下面的操作,也就由这个对象来进行,如我上面的展示的源码中的删除操作.

    所以我们集成多种模式的redis工作,就从这里确定了,那就是提供多个操作对象,比如集合,下面对应的操作也遍历循环成单个操作对象后再操作.

    1.引入jar包

    同普通集成一样.

    2.以RedisSessionRepository为模板重写自定义的RedisSessionRepostory类

    这里的工作比较简单,就是将单个操作对象变集合,下面对应的操作,变成遍历集合后再操作,但是注意要跟RedisSessionRepository一样去实现对应的接口:

    public class DistributeRedisSessionRepository implements SessionRepository<DistributeRedisSessionRepository.RedisSession> {
    
    	private static final String DEFAULT_KEY_NAMESPACE = "spring:session:";
    
    	//private final RedisOperations<String, Object> sessionRedisOperations;
    	private final List<RedisOperations<String, Object>> sessionRedisOperationss;
    
    	@Override
    	public void deleteById(String sessionId) {
    		String key = getSessionKey(sessionId);
    		//this.sessionRedisOperations.delete(key);
    		//批量删除
    		for (RedisOperations<String, Object> redisOperations: this.sessionRedisOperationss){
    			redisOperations.delete(key);
    		}
    	}
    

    这里,我们自己的DistributeRedisSessionRepository类改造完成.

    3.将源码中的RedisSessionMapper复制一份

    因为,自定的DistributeRedisSessionRepository类中有用到RedisSessionMapper这个类,那我们可以从源码中将这个类拷贝出来,与自定义的那个类放同一级别即可.

    4.利用自定义的DistributeRedisSessionRepository注册给spring-redis

    因为我们自定义了DistributeRedisSessionRepository,spring并不知道这个类,那我们就要将其注册给spring.

    先利用@EnableSpringHttpSession注解开启springsession,如下:

    /**
     * 用于配置spring-session 及关联的 redis配置
     * @author 愉快淡定
     */
    @Slf4j
    @Configuration
    @EnableSpringHttpSession
    public class DistributeSpringRedisSessionConfig{
        
        private ArrayList<RedisOperations<String, Object>> redisOperations = new ArrayList<>();
    

    可以看到我自定义了DistributeSpringRedisSessionConfig类,属性redisOperations(用于存放多种模式redis操作对象,对应自定义的DistributeRedisSessionRepository中的修改),那么后续的配置在这里进行.

    5.提供多种模式的redis操作对象

    这里提供两种模式的,至于cluster各位看官应该能根据普通集成或者通过这两种示例自行集成进来.强调,这里的三种模式并非互斥,而是可以共存,甚至可以同时存在多种同一模式的配置(我项目中同时存在两个Standalone模式的操作对象).

    5.1.集成Standalone模式的操作对象

    我的redis配置较多,各位看官可以根据自己需要进行配置,添加删除都行,或者简单默认也ok.

    @Bean("masterRedisTemplate")
    public RedisOperations<String, Object> masterSessionRedisOperations() {
        RedisTemplate<String, Object> masterRedisTemplate = new RedisTemplate<>();
        RedisStandaloneConfiguration masterRedisStandaloneConfiguration = new RedisStandaloneConfiguration(masterHostName, masterPort);
        JedisClientConfiguration.DefaultJedisClientConfigurationBuilder jd = (JedisClientConfiguration.DefaultJedisClientConfigurationBuilder)JedisClientConfiguration.builder();
        jd.readTimeout(Duration.ofMillis(this.masterTimeout));
        jd.connectTimeout(Duration.ofMillis(this.masterTimeout));
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setTestOnBorrow(masterTestOnBorrow);
        poolConfig.setMaxIdle(masterMaxIdle);
        poolConfig.setMinIdle(masterMinIdle);
        poolConfig.setMaxWaitMillis(masterMaxWait);
        poolConfig.setMaxTotal(masterMaxActive);
        jd.poolConfig(poolConfig);
        jd.usePooling();
        RedisConnectionFactory masterRedisConnectionFactory = new JedisConnectionFactory(masterRedisStandaloneConfiguration,jd.build());
        masterRedisTemplate.setConnectionFactory(masterRedisConnectionFactory);
        masterRedisTemplate.setKeySerializer(new StringRedisSerializer());
        masterRedisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        masterRedisTemplate.setHashKeySerializer(new StringRedisSerializer());
        masterRedisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
        //设置模板其他配置
        redisOperations.add(masterRedisTemplate);
        return masterRedisTemplate;
    }
    
    	@Bean
        public DistributeRedisSessionRepository sessionRepository() {
            Duration duration = Duration.ofSeconds(maxlive);
            return new DistributeRedisSessionRepository(redisOperations,duration);
        }
    

    5.2.集成Sentinel模式的操作对象

    @Bean("sentinelRedisTemplate")
    public RedisOperations<String, Object> sentinelSessionRedisOperations() {
        RedisTemplate<String, Object> sentinelRedisTemplate = new RedisTemplate<>();
        RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration()
                .master("mymaster")
                .sentinel("10.70.33.238", 26379)
                .sentinel("10.70.33.239", 26379)
                .sentinel("10.70.33.246", 26379);
        RedisConnectionFactory sentinelRedisConnectionFactory = new JedisConnectionFactory(redisSentinelConfiguration);
        sentinelRedisTemplate.setConnectionFactory(sentinelRedisConnectionFactory);
        sentinelRedisTemplate.setKeySerializer(new StringRedisSerializer());
        sentinelRedisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        sentinelRedisTemplate.setHashKeySerializer(new StringRedisSerializer());
        sentinelRedisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
        redisOperations.add(sentinelRedisTemplate);
        return sentinelRedisTemplate;
    }
    
    	@Bean
        public DistributeRedisSessionRepository sessionRepository() {
            Duration duration = Duration.ofSeconds(maxlive);
            return new DistributeRedisSessionRepository(redisOperations,duration);
        }
    

    5.3 集成Cluster模式的操作对象

    略,各位看官如有需要,根据上面两种模式的集成方式自行集成即可.

    6.启动测试

    启动测试同上面的普通集成中的启动测试.

    四.结束

    以上是根据最近项目需求进行的springboot+spring-session+spring-redis的集成工作,我这里实际遇到的情况是项目中的redis配置非官方那种配置,同时,需要集成两个Standalone的redis来存储session信息,哨兵模式及集群模式尚未实际用到,提供的解决方案供各位看官参考,能帮到各位最好,不能也希望各位勿怪.如果能提出意见给我,我这边也会十分感谢,谢谢各位.

    展开全文
  • 公众号: java乐园 HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。...那问题来了,如何保证不同的服务器能够共享同一份...最简单的想法,就是把session数据保存到内存以外的一个统一...

    公众号: java乐园

    HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。但是把应用搭建成分布式的集群,然后利用F5、LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被分发到多个不同的服务器中。那问题来了,如何保证不同的服务器能够共享同一份session数据呢?最简单的想法,就是把session数据保存到内存以外的一个统一的地方,例如Memcached/Redis等数据库中。那问题又来了,如何替换掉Servlet容器创建和管理的HttpSession的实现呢?
      方案一:利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略。这方面其实早就有开源项目了,例如memcached-session-manager(可以参考负载均衡+session共享(memcached-session-manager实现),以及tomcat-redis-session-manager。不过这种方式有个缺点,就是需要耦合Tomcat/Jetty等Servlet容器的代码。
      方案二:设计一个Filter,利用HttpServletRequestWrapper,实现自己的 getSession()方法,接管创建和管理Session数据的工作。spring-session就是通过这样的思路实现的。

    在这里插入图片描述

    1、 新建项目sc-redis-session,对应的pom.xml文件如下

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>spring-cloud</groupId>
    	<artifactId>sc-redis-session</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>sc-redis-session</name>
    	<url>http://maven.apache.org</url>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.0.4.RELEASE</version>
    	</parent>
    
    	<dependencyManagement>
    		<dependencies>
    			<dependency>
    				<groupId>org.springframework.cloud</groupId>
    				<artifactId>spring-cloud-dependencies</artifactId>
    				<version>Finchley.RELEASE</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
    
    		</dependencies>
    	</dependencyManagement>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<maven.compiler.source>1.8</maven.compiler.source>
    		<maven.compiler.target>1.8</maven.compiler.target>
    	</properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-redis</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-pool2</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.session</groupId>
    			<artifactId>spring-session-data-redis</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>com.alibaba</groupId>
    			<artifactId>fastjson</artifactId>
    			<version>1.2.49</version>
    		</dependency>
    	</dependencies>
    </project>
    

    2、 新建springboot启动类RedisSessionApplication.java

    package com.redis.session;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
    
    @SpringBootApplication
    @EnableRedisHttpSession
    public class RedisSessionApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(RedisSessionApplication.class, args);
    	}
    }
    

    说明:主要使用EnableRedisHttpSession注解开启spring分布式session,该类的作用是配置org.springframework.session.web.http.SessionRepositoryFilter进行请求拦截
    3、 新建配置文件application.yml

    server:
      port: 7200
    spring:
      session:
        store-type: redis
      application:
        name: sc-redis-session
      redis:
        host: 127.0.0.1
        password: 
        port: 6379
        timeout: 10000 # 连接超时时间(毫秒)
        database: 0 # Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
        lettuce:
          pool:
            max-active: 8 # 连接池最大连接数(使用负值表示没有限制) 默认 8
            max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
            max-idle: 8 # 连接池中的最大空闲连接 默认 8
            min-idle: 0 # 连接池中的最小空闲连接 默认 0
    

    4、 新建一个UserController

    package com.redis.session.controller;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.alibaba.fastjson.JSON;
    import com.redis.session.model.User;
    
    @RestController
    public class UserController {
    
    	private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    
    	/**
    	 * 把用户放入session
    	 * 
    	 * @param request
    	 * @return
    	 */
    	@RequestMapping("/user/login")
    	@ResponseBody
    	public Map<String, Object> login(HttpServletRequest request) {
    		// 取出session中的userName
    		Object loginUser = request.getSession().getAttribute("loginUser");
    		if (loginUser == null) {
    			logger.info("不存在session,设置user");
    			User u = new User();
    			u.setAge(23);
    			u.setId(1L);
    			u.setPosition("总裁");
    			u.setUserName("huangjinjin");
    			request.getSession().setAttribute("loginUser", u);
    		} else {
    			logger.info("存在session,user=" +  JSON.toJSONString(loginUser));
    		}
    		Cookie[] cookies = request.getCookies();
    		if (cookies != null && cookies.length > 0) {
    			for (Cookie cookie : cookies) {
    				logger.info(cookie.getName() + " : " + cookie.getValue());
    			}
    		}
    		Map<String, Object> resp = new HashMap<String, Object>();
    		resp.put("code", "000000");
    		resp.put("msg", "交易成功");
    		return resp;
    	}
    
    	/**
    	 * 获取session的用户
    	 * 
    	 * @param request
    	 * @return
    	 */
    	@RequestMapping("/user/getUser")
    	@ResponseBody
    	public Map<String, Object> getUser(HttpServletRequest request) {
    		Map<String, Object> resp = new HashMap<String, Object>();
    		resp.put("code", "000000");
    		resp.put("msg", "交易成功");
    		resp.put("body", request.getSession().getAttribute("loginUser"));
    		Cookie[] cookies = request.getCookies();
    		if (cookies != null && cookies.length > 0) {
    			for (Cookie cookie : cookies) {
    				logger.info(cookie.getName() + " : " + cookie.getValue());
    			}
    		}
    		return resp;
    	}
    	
    }
    

    5、 启动项目,查看日志是否启动成功

    在这里插入图片描述

    6、 使用谷歌浏览器访问接口
    第一次访问登录接口:http://127.0.0.1:7200/user/login
    在这里插入图片描述
    控制台打印:
    在这里插入图片描述
    第二次至第n次:控制台打印
    在这里插入图片描述

    访问获取session接口:返回对应的用户数据
    在这里插入图片描述
    7、 通过reids客户端redis-cli查看redis服务器的数据

    在这里插入图片描述

    展开全文
  • 首先还是吐槽,百度了两天,尝试了十多种方案,各种重写,无效。。。。。最后,还是在官网找到解决方案。 哎。。...很简单,相同的用户登录时,只能保留最后一个session。...springboot+spring session redis+spring...

    首先还是吐槽,百度了两天,尝试了十多种方案,各种重写,无效。。。。。最后,还是在官网找到解决方案。

    哎。。。已经很多次了。官网。官网。官网。。以后要多看官网。

     

    还是描述下需求吧。很简单,相同的用户登录时,只能保留最后一个session。防止多处登录。也不算是单点。

    在开始贴代码之前,各位看官一定要注意条件

    springboot+spring session redis+spring security ,使用java config方式。

    可能不使用spring session redis 或者 spring security的情况,不会出现我的问题,因为不涉及redis session的控制。

     

    一般情况下,如果使用spring自带的内存管理方式,非常简单就可以实现(没有尝试,看百度应该问题不大)

    springsecurity配置中

    @Override
    	protected void configure(HttpSecurity http) throws Exception {
    ....
    http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(false).expiredUrl("/login?expired");
    		
    	}

    而使用了spring session  redis,则在spring security对登陆session控制的默认实现类SessionRegistryImpl中判断session时,无法获取正确的获取session。特别是重启应用后,基于内存的SessionRegistryImpl就会丢失session,而redis中的还存在。登陆成功的用户还能操作,而SessionRegistryImpl中,则没有任何session了。

    所以,解决方案是,在springsecurity配置中,注册spring session redis 的sessionregistry。代码如下(20191024修改):

    @Configuration
    @Import({ SessionRedisConfig.class })
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true) // 开启security注解
    public class WebSecurityConfig<S extends Session> extends WebSecurityConfigurerAdapter {
    	
    	@Autowired
    	private FindByIndexNameSessionRepository<S> sessionRepository;
    	
    	
    	@Override
    	protected void configure(HttpSecurity http) throws Exception {
    
    		// 允许所有用户访问"/"和"/register"
    		http.authorizeRequests().antMatchers("/", "/public/**","/static/**", "/login").permitAll()
    				.antMatchers("/admin/**").hasRole("ADMIN")
    				// 其他地址的访问均需验证权限
    				.anyRequest().authenticated()// .hasRole("USER")
    				.and().formLogin()
    				// 指定登录页是"/login"
    				.loginPage("/login")
    				// .failureUrl("/login?error=true")
    				.defaultSuccessUrl("/main").permitAll()
    				.and().headers().frameOptions().disable().and().logout()
    				.logoutUrl("/logout").logoutSuccessUrl("/").permitAll();
    		http.exceptionHandling().accessDeniedPage("/403")
    			.and().csrf().disable();
    		//not create new session
    		http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
    		//ori session user
    		http.sessionManagement().sessionFixation().none();
    		http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(false).expiredUrl("/login")
    		.sessionRegistry(sessionRegistry());
    		//http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
    	}
    	
    	@Bean
        SpringSessionBackedSessionRegistry<S> sessionRegistry() {
                return new SpringSessionBackedSessionRegistry<S>(sessionRepository);
        }
    	
    	

     

    展开全文
  • Spring全家桶之SpringSession

    万次阅读 多人点赞 2019-09-15 20:11:52
    SpringSessionSpringSession MongoDB相关的实用知识的整理 ,希望能够帮助更多人~~~

    第一章 HttpSession

    一、 HttpSession 回顾

    1. 什么是 HttpSession
      是 JavaWeb 服务端提供的用来建立与客户端会话状态的对象。

    二、 Session 共享

    1. 什么是 Session 共享
      是指在一个浏览器访问多个 Web 服务时,服务端的 Session 数据需要共享。

    2. Session 共享应用场景

      • 单点登录
      • Web 服务器集群等场景
    3. Session 共享常见的解决方案

      Session 复制
      通过对应用服务器的配置开启服务器的 Session 复制功能,在集群中的几台服务器之间同步 Session 对象,使得每台服务器上都保存所有的 Session 信息,这样任何一台宕机都不会导致 Session 的数据丢失,服务器使用 Session 时,直接从本地获取。这种方式的缺点也比较明显。因为 Session 需要时时同步,并且同步过程是有应用服务器来完成,由此对服务器的性能损耗也比较大。

      Session 绑定
      利用 hash 算法,比如 nginx 的 ip_hash,使得同一个 Ip 的请求分发到同一台服务器上。 这种方式不符合对系统的高可用要求,因为一旦某台服务器宕机,那么该机器上的 Session 也就不复存在了,用户请求切换到其他机器后么有 Session,无法完成业务处理。

      利用 Cookie 记录 Session
      Session 记录在客户端,每次请求服务器的时候,将 Session 放在请求中发送给服务器, 服务器处理完请求后再将修改后的 Session 响应给客户端。这里的客户端就是 cookie。 利用 cookie 记录 Session 的也有缺点,比如受 cookie 大小的限制,能记录的信息有限, 安全性低,每次请求响应都需要传递 cookie,影响性能,如果用户关闭 cookie,访问就不正常。

      Session 服务器
      Session 服务器可以解决上面的所有的问题,利用独立部署的 Session 服务器统一管理 Session,服务器每次读写 Session 时,都访问 Session 服务器。 对于 Session 服务器,我们可以使用 Redis 或者 MongoDB 等内存数据库来保存 Session 中的数据,以此替换掉服务中的 HttpSession。达到 Session 共享的效果。

    三、SpringSession的简介

    Spring Session 是 Spring 的项目之一。Spring Session 提供了一套创建和管理 Servlet HttpSession 的方案,默认采用外置的 Redis 来存储 Session 数据,以此来解决 Session 共享的 问题。

    四、 SpringSession 的使用

    安装Redis单机版

    点击查看单机版安装

    共享简单数据

    搭建案例环境

    项目简单介绍,创建了一个父项目,两个聚合模块的子项目
    父项目为pom项目
    子项目为jar项目

    在这里插入图片描述

    1.创建父项目

    创建项目 ,修改pom文件

    注 :需要继承SpringBoot父项目的启动器,添加项目运行环境,相关的jar

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      	<!-- SpringBoot父项目的启动器 -->
      	   <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.7.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
         </parent>
      <groupId>ah.szxy.springsession</groupId>
      <artifactId>01-SpringSession</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>pom</packaging>
    
    
     <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-core</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <!--Spring session data redis-->
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
                <!--<version>2.1.4.RELEASE</version>-->
            </dependency>
            <!--Lettuce是 一 个 基 于 Netty的 NIO方 式 处 理 Redis的 技 术 -->
            <dependency>
                <groupId>io.lettuce</groupId>
                <artifactId>lettuce-core</artifactId>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    

    2.创建两个子项目

    session_service1,session_service2

    1. pom文件(二者除名称外相同)

      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
          <groupId>ah.szxy.springsession</groupId>
          <artifactId>01-SpringSession</artifactId>
          <version>0.0.1-SNAPSHOT</version>
        </parent>
        <artifactId>session_service1</artifactId>
      
      
      <properties>
      	<java.version>1.8</java.version>
      	<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
      </properties>
      </project>
      

      注意 :在添加properties内的代码后,即可解决pom文件第一行报异常的问题

    2. 全局配置文件(除应用名, 端口号外相同)

      spring:
        application:
          name: Spring-Session-Servlet1
        redis:
          #redis单机配置
          host: 192.168.179.131
          port: 6379
          # 选择redis的数据库的分库
          database: 5
          #redis连接池配置
          jedis:
            pool:
              max-idle: 10
              min-idle: 5
              max-active: 100
              max-wait: 3000
              timeout: 6005
              
      server:
        port: 8081
        
      
    3. 启动类(相同)

      package ah.szxy;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
      
      /**
       * @EnableRedisHttpSession开启redis对SpringSession的支持
       * @author chy
       *
       */
      @SpringBootApplication
      @EnableRedisHttpSession
      public class SpringSessionApp {
      	public static void main(String[] args) {
      		SpringApplication.run(SpringSessionApp.class, args);
      	}
      }
      
      
    1. session_service1 :Controller

      @RestController
      @RequestMapping("service1")
      public class WebController {
      	
      	@RequestMapping("setMsg")
      	public String  getMsg(HttpSession session) {
      		
      		session.setAttribute("msg", "Hello SpringSession!");
      		return "ok";
      	}
      }
      
    2. session_service2 :Controller

      @RestController
      @RequestMapping("service2")
      public class WebController {
      	
      	@RequestMapping("getMsg")
      	public String  getMsg(HttpSession session) {
      		
      		String msg=(String) session.getAttribute("msg");
      		return msg;
      	}
      }
      
      

    3.测试结果
    访问session_service1的controller查看结果
    在这里插入图片描述

    查看redis数据库是否存放了session数据

    在这里插入图片描述
    默认的保存的时间约为2100s

    访问session_service2 的controller查看结果
    在这里插入图片描述

    共享自定义对象

    在上面的案例中进行修改

    1.两个子模块都添加实体类

    因为涉及对象类型数据传输到redis,故需要实现序列化接口

    package ah.szxy.domain;
    
    import java.io.Serializable;
    
    public class Users implements Serializable{
    	
    	private String username;
    	private String userpwd;
    	public String getUsername() {
    		return username;
    	}
    	public void setUsername(String username) {
    		this.username = username;
    	}
    	public String getUserpwd() {
    		return userpwd;
    	}
    	public void setUserpwd(String userpwd) {
    		this.userpwd = userpwd;
    	}
    	@Override
    	public String toString() {
    		return "Users [username=" + username + ", userpwd=" + userpwd + "]";
    	}
    	public Users() {
    		super();
    	}
    	public Users(String username, String userpwd) {
    		super();
    		this.username = username;
    		this.userpwd = userpwd;
    	}
    	
    	
    }
    
    

    2.子模块1的controller

    @RequestMapping("addUser")
    	public String addUser(HttpSession session,Users user) {
    		
    		session.setAttribute("user", user);
    		return "addUser Success!!!";
    	}
    

    3.测试结果

    访问session_service1的controller查看结果
    查看redis数据库是否存放了session数据
    访问session_service2 的controller查看结果

    在这里插入图片描述

    在这里插入图片描述

    SpringSession 的 Redis 存储结构

    spring:session:expirations:(Set 结构)

    用户 ttl 过期时间记录 , 这个 key中的值是一个时间戳,
    根据这个 Session 过期时刻滚动至下一分钟而计算得出。
    这个 key 的过期时间为 Session 的最大过期时间 +5 分钟(再此为2100s)。

    在这里插入图片描述

    spring:session:sessions:(Hash 结构)
    maxInactiveInterval:过期时间间隔
    creationTime:创建时间
    lastAccessedTime:最后访问时间
    sessionAttr:Attributes 中的数据存储 Session 的详细信息,包括 Session 的过期时间间隔、最后的访问时间、attributes 的值。这个 key 的过期时间为 Session 的最大过期时间 +5 分钟。

    在这里插入图片描述
    spring:session:sessions:expires:(String 结构)

    过期时间记录 : 这个 k-v 不存储任何有用数据,只是表示 Session 过期而设置。
    这个 key 在 Redis 中的过期时间即为 Session 的过期时间间隔

    在这里插入图片描述

    设置session的失效时间

    修改启动类的@EnableRedisHttpSession注解

    @SpringBootApplication
    /**
     * 设置超时时限
     * 需要两端同步,单位秒
     */
    @EnableRedisHttpSession(maxInactiveIntervalInSeconds=20)
    @SpringBootApplication
    public class SessionServlet1Application {
        public static void main(String[] args) {
            SpringApplication.run(SessionServlet1Application.class, args);
        }
    }
    

    @EnableRedisHttpSession注解中相关属性讲解

    点击注解即可进入相应的注解接口 ,可以看到其中有四个属性
    在这里插入图片描述

    属性作用
    maxInactiveIntervalInSeconds设置 Session 的失效时间,单位为秒。默认(1800 秒)30 分钟。
    redisNamespace为键定义唯一的命名空间。该值用于通过更改前缀与默认 spring:session 隔离会话
    redisFlushModeRedis 会话的刷新模式。默认值为“保存”
    cleanupCron过期会话清理作业的 cron 表达式。默认值(“0 *****”)每分钟运行一次。

    更换 SpringSession 的序列化器

    SpringSession 中默认的序列化器为 jdk 序列化器,该序列化器效率低下,内存再用大。
    我们可以根据自己的需要更换其他序列化器,如 GenericJackson2JsonRedisSerializer 序列化器。
    使用配置类跟换序列器

    /**
     * 1.需要两端都添加这个配置类
     * 2.同时允许关联对象的添加
     * @author 曹海洋
     *
     */
    @Configuration
    public class SpringSessionConfig {
    	
    	/**
         * 更换序列化器
         * @return
         */
        @Bean("springSessionDefaultRedisSerializer")
        public RedisSerializer setSerializer(){
            return new GenericJackson2JsonRedisSerializer();
        }
        
    }
    

    注意 :
    1.如果在项目中使用序列化其,建议使用这里推荐的序列化器序列化器的配置类
    2.将原来的数据清空
    3.不要额外导入jar, 上面添加的坐标包含的jar足够

    配置前

    在这里插入图片描述
    配置后
    在这里插入图片描述

    第二章 Spring Session MongoDB

    一、SpringSessionMongoDB 简介

    1 什么是Spring Session MongoDB
    Spring Session MongoDB 是Spring Session 的二级项目。其功能与Spring Session 是相同的。
    Spring Session MongoDB 提供了一个API 和实现,用于通过利用Spring Data MongoDB来管理存储在MongoDB 中的用户会话信息。

    2 与Spring Session 的区别
    Spring Session 与Spring Session MongoDB 的作用相同的。都是来解决Session 共享问题
    不同的是Spring Session 默认的是依赖于Redis 作为数据缓存平台,而Spring SessionMongoDB 是依赖于MongoDB 来作为数据缓存平台的。

    二、Spring Session MongoDB 的使用

    安装MongoDB单机版

    1. 下载 MongoDB

      本次使用版本: mongodb-linux-x86_64-4.0.9.tgz

    2. 解压 tgz 文件并复制到/usr/local目录下

      tar-zxfmongodb-linux-x86_64-4.0.9.tgz
      
      cp mongodb-linux-x86_64-4.0.9 /usr/local/mongodb -rf
      
    3. 进入mongodb目录下, 创建数据库目录

      mkdir -p data/db
      
    4. 创建一个文件夹etc, 统一存放日志文件和配置文件

      mkdir etc
      
    5. 创建日志文件

      touch mongodb.log
      
    6. 创建配置文件

       vim mongodb.conf
      

      配置文件中的内容

      dbpath=/usr/local/mongodb/data/db
      logpath=/usr/local/mongodb/etc/mongodb.log
      port=27017
      fork=true
      bind_ip=0.0.0.0
      

      在这里插入图片描述

    7. 启动 MongoDB

       ./mongod --config /usr/local/mongodb/etc/mongodb.conf
      
    8. 创建自定义库(chy)

      #登录客户端
        ./mongo
       
      #库存在就切换到该库,不存在就创建
      use chy
      
    9. 常用操作指令

      #1. 启动 
       ./mongod  --config 配置文件位置
      #列如:
       ./mongod  --config /usr/local/mongodb/etc/mongodb.conf
      
      
      #2. 关闭
      ./mongod --shutdown --config 配置文件位置
      #例如:
      ./mongod --shutdown --config /usr/local/mongodb/etc/mongodb.conf
      

    共享简单数据

    环境搭建

    创建一个父项目,两个子项目
    父项目为pom项目,规定所用jar版本与种类
    子项目为jar项目,实现具体的模拟内容

    在这里插入图片描述

    1.创建父项目,修改pom文件

    <project xmlns="http://maven.apache.org/POM/4.0.0"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.1.7.RELEASE</version>
    		<relativePath /> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>ah.szxy.springSession</groupId>
    	<artifactId>02-SpringSession-MongoDB</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>pom</packaging>
    
    	<properties>
    		<java.version>1.8</java.version>
    		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
    	</properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.session</groupId>
    			<artifactId>spring-session-core</artifactId>
    		</dependency>
    		<!--Spring session data mondodb -->
    		<dependency>
    			<groupId>org.springframework.session</groupId>
    			<artifactId>spring-session-data-mongodb</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-mongodb</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    	<modules>
    		<module>session_mongo2</module>
    	</modules>
    </project>
    

    2.创建两个子项目,无需修改pom文件

    <project xmlns="http://maven.apache.org/POM/4.0.0"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>ah.szxy.springSession</groupId>
    		<artifactId>02-SpringSession-MongoDB</artifactId>
    		<version>0.0.1-SNAPSHOT</version>
    	</parent>
    	<artifactId>session_mongo1</artifactId>
    </project>
    

    注意:两个pom文件除名称不一样外,其他一致

    3.修改全局配置文件 application.yml

    server:
      port: 8081
    spring:
      application:
        name: Session-Mongdb1
      session:
        store-type: mongodb
      data:              #配置MongoDB的连接参数
        mongodb:
          host: 192.168.179.131
          port: 27017
          database: chy  #自定义MongoDB库名称
    

    注意:两个配置文件处理应用名,端口号不一样外,其他一致

    4.启动类

    package ah.szxy;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
    
    @SpringBootApplication
    @EnableMongoHttpSession
    public class SessionMongoApp {
    	
    	public static void main(String[] args) {
    		SpringApplication.run(SessionMongoApp.class, args);
    	}
    }
    
    

    注:两个启动类完全一致

    4.session_mongo1的controller

    @RestController
    @RequestMapping("service1")
    public class MongoDBController {
    	
    	@RequestMapping("setMsg")
    	public String showMsg(HttpSession session) {
    		
    		session.setAttribute("msg", "Hello MongoDB!!!");
    		return "ok";
    	}
    }
    

    5.session_mongo2的controller

    @RestController
    @RequestMapping("service2")
    public class MongoDBController {
    	
    	@RequestMapping("getMsg")
    	public String showMsg(HttpSession session) {
    		
    		String msg = (String) session.getAttribute("msg");
    		return msg;
    	}
    }
    

    6.测试结果

    启动两个项目, 访问session_mongo1的controller
    在这里插入图片描述
    访问session_mongo2的controller
    在这里插入图片描述

    共享自定义对象

    1.两个子模块都要创建Users实体类

    package ah.szxy.domain;
    
    import java.io.Serializable;
    
    public class Users implements Serializable{
    	
    	private String username;
    	private String userpwd;
    	public String getUsername() {
    		return username;
    	}
    	public void setUsername(String username) {
    		this.username = username;
    	}
    	public String getUserpwd() {
    		return userpwd;
    	}
    	public void setUserpwd(String userpwd) {
    		this.userpwd = userpwd;
    	}
    	@Override
    	public String toString() {
    		return "Users [username=" + username + ", userpwd=" + userpwd + "]";
    	}
    	public Users() {
    		super();
    	}
    	public Users(String username, String userpwd) {
    		super();
    		this.username = username;
    		this.userpwd = userpwd;
    	}
    	
    	
    }
    
    

    注意:勿忘实现序列化接口

    2.session_mongo1的controller中添加方法

    	@RequestMapping("addUser")
    	public String showMsg(HttpSession session,Users user) {
    		
    		session.setAttribute("user", user);
    		return "ok";
    	}
    

    3.session_mongo2的controller中添加方法

    	@RequestMapping("getUser")
    	public Users showUser(HttpSession session) {
    		
    		Users user=(Users) session.getAttribute("user");
    		return user;
    	}
    

    4.测试结果

    在这里插入图片描述

    在这里插入图片描述

    SpringSession MongoDB 的存储结构

    使用其专用的查询语句即可查看它的存储结构

    在这里插入图片描述

    整理如下 点击使用json格式校验/转换

    {
    	"_id": "138af2fe-cf3f-4e8d-8ea1-a311ecd70edc",
    	"created": ISODate("2019-09-16T08:42:51.767Z"),
    	"accessed": ISODate("2019-09-16T09:07:10.425Z"),
    	"interval": "PT30M",
    	"principal": null,
    	"expireAt": ISODate("2019-09-16T09:37:10.425Z"),
    	"attr": BinData(0, "rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAACdAADbXNndAAQSGVsbG8gTW9uZ29EQiEhIXQABHVzZXJzcgAUYWguc3p4eS5kb21haW4uVXNlcnOYj4Y/edg3CAIAAkwACHVzZXJuYW1ldAASTGphdmEvbGFuZy9TdHJpbmc7TAAHdXNlcnB3ZHEAfgAGeHB0AANjaHl0AAl0aW1lcGF1c2V4")
    }
    

    设置session的失效时间

    /**
     * @EnableMongoHttpSession
     * maxInactiveIntervalInSeconds: 设置超时时限, 两个子模块的这个属性必须一致
     * collectionName: 可省略,唯一标识,使用时两个子模块的这个属性必须一致
     */
    @SpringBootApplication
    @EnableMongoHttpSession(maxInactiveIntervalInSeconds=20,collectionName="test")
    public class SessionMongoApp {
    	
    	public static void main(String[] args) {
    		SpringApplication.run(SessionMongoApp.class, args);
    	}
    }
    

    注意 : @EnableMongoHttpSession注解的两个属性的用法

    @EnableMongoHttpSession 注解中相关属性讲解

    属性作用
    maxInactiveIntervalInSeconds设置 Session 失效时间 ,默认为2100s
    collectionName设置 MongoDB 的 Collections 的名称 ,默认为seesions

    更换 SpringSession 的序列化器

    默认使用的是jdk序列化器,序列化后产生的数据较大,占用内存较高,因此最好换成其他的序列化器

    1. 使用配置类修改序列化器
    @Configuration
    public class SerializableConfig {
    
        @Bean
        JacksonMongoSessionConverter mongoSessionConverter() {
            return new JacksonMongoSessionConverter();
        }
    
    }
    

    启动项目时报错,因为json转换时对对象的属性做了校验,
    而自定义对象的属性不在白名单中,我们需要关闭属性的自动校验

    1. 在实体类上添加注解关闭自动校验
    @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)
    public class User implements Serializable {
    	private String username;
    	private String userpwd;
    	...
    }
    

    mongodb中存储的数据

    {
        "_id" : "36d3dd35-e33d-49f8-bde9-ec3587e2d560",
        "@class" : "org.springframework.session.data.mongo.MongoSession",
        "createdMillis" : NumberLong(1566549133774),
        "accessedMillis" : NumberLong(1566549137807),
        "intervalSeconds" : 20,
        "expireAt" : ISODate("2019-08-23T08:32:37.807Z"),
        "attrs" : {
            "@class" : "java.util.HashMap",
            "user" : {
                "@class" : "cn.xyl.pojo.User",
                "_id" : 123,
                "name" : "hello"
            }
        },
        "principal" : null
    }
    
    展开全文
  • 2.1.5.RELEASE由于spring-boot-starter-parent 2.1.5.RELEASE中的会话需要安全性支持,故此需要约会安全性,✓安全性依赖后,Security默认开启,如果不使用Security,而不是使用WebSecurityConfigurerAdapterConfig...
  • 背景: 未跨域Ajax异步请求时,session保持不变 未跨域时Ajax请求不同的action时,session保持不变 跨域Ajax异步请求时,每次请求都是一个新的session 一些帖子供参考 http:
  • 1、在pom中添加如下依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependenc.
  • 在执行登录动作时,在successhandler中,当有流开启对响应头做出修改时就会触发一个onResponseCommit方法,里面调用了HttpSessionSecurityContextRepository.saveContent的方法对session写入或更新 @Override ...
  • 上次小黑在文章中介绍了四种分布式一致性 Session 的实现方式,在这四种中最常用的就是后端集中存储方案,这样即使 web 应用重启或者扩容,Session 都没有丢失的风险。 今天我们就使用这种方式对 Session 存储方式...
  • 现在都比较流行使用spring boot来进行开发,使用spring cloud来搭建分布式。在搭建的时候会涉及到一个关键的问题,session统一的问题。使用zuul作为网关转发来调用其他模块,zuul中的session和其他模块的session会不...
  • spring使用Redis存储Session 准备 spring web的maven项目 配置 pom.xml添加依赖 org.springframework.session spring-session 1.0.2.RELEASE org.springframework.data spring-data-redis
  • Spring Boot + Spring Session + Redis 进行session共享,nginx进行反向代理
  • SpringSession 简单使用

    2020-04-16 18:47:53
    导航目录楔子session 共享问题解决1 session复制2 hash一致性3 统一存储4 session共享问题解决-不同服务,子域session共享|(springSessionSpringSession 简单使用1 pom引入依赖2 使用注解开启 springsession3 ...
  • import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.FlushMode;...import org.hibernate.Session; import org.hibernate.SessionFactory; import org.j
  • spring boot之Spring session配置

    万次阅读 2018-12-20 18:44:47
    为什么要spring-session 在传统单机web应用中,一般使用tomcat/jetty等web容器时,用户的session都是由容器管理。浏览器使用cookie中记sessionId,容器根据sessionId判断用户是否存在会话session。这里的限制是,...
  • springboot 整合 spring sessionsession共享

    万次阅读 热门讨论 2018-12-19 20:59:38
    今天给大家简单介绍下spring session的使用。本篇主要介绍使用redis做存储,话不多说直接撸代码。 – 下面是pom 只需要额外引入redis 和 session的jar就ok。 &amp;amp;lt;dependency&amp;amp;gt; &amp...
  • 开启事件通知配置(默认spring session会自动开启该配置) 配置文件:notify-keyspace-events Ex 命令行:redis-cli config set notify-keyspace-events Egx 不需要自动开启该配置的话可以将如下配置加入到容器中 ...
  • Spring Boot分布式Session

    2018-05-17 17:36:09
    添加所需依赖添加 application.properties redis 以及session 的配置信息添加@EnableRedisHttpSession来开启spring session支持
  • spring session管理

    2018-08-23 16:55:43
    spring session管理可以适用于很多功能,如: 登陆/退出 在线统计 限制账号多处登陆等 2. 监听器 相关的监听器主要有两个:HttpSessionListener和HttpSessionBindingListener 1. HttpSessionBindingListener ...
  • spring security控制session

    万次阅读 2018-02-25 20:10:40
    spring security控制session 本文给你描述在spring security中如何控制http session。包括session超时、启用并发session以及其他高级安全配置。 创建session时机 我们可以准确地控制什么时机创建session,有...
  • 最近使用spring boot开发一个系统,nginx做负载均衡分发请求到多个tomcat,此时访问页面会把请求分发到不同的服务器,session是存在服务器端,如果首次访问被分发到A服务器,那么session就会被存到A服务器,再次访问...
  • [Spring实战系列](3)开启Spring之门

    千次阅读 2016-01-31 23:01:57
    百度百科这么说明SpringSpring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生...
  • springboot+Spring-security+Spring-Session+Redis+nginx 实现 Session 共享示例说明版本示例安装Spring-Session:Springboot 中开启 Spring-sessionSpringboot 中自定义 Session注意 HttpSession是通过Servlet容器...
  • 今天记录一下学习的springSession以及遇到的坑 下载redisDesktopManager 1.SpringSession依赖导入pom文件 <dependency> <groupId>org.springframework.session</groupId> <artifactId...
  • spring session原理

    千次阅读 2017-10-24 15:16:11
    spring session是干什么的,有什么作用?这些读者可以自行从百度上找到,本文主要是从配置、原理、流程等几个方面来了解spring session
  • 目录1 HttpSession 回顾1.1 什么是 HttpSession2 Session 共享2.1 什么是 Session 共享2.2 Session 共享应用...Spring Session5 Spring Session 的使用5.1 安装 Redis5.2 搭建案例环境5.2.1 版本介绍5.2.2 创建项目5.3
  • Spring-session+mongodb实现session共享

    千次阅读 2018-10-30 15:52:57
    Spring-session+mongodb实现session共享pom.xml配置web.xml配置applicationContext.xml 核心配置文件在系统中使用session pom.xml配置 首先需要引入依赖包,直接在pom.xml中添加以下代码即可。 &amp;lt;!--...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 49,545
精华内容 19,818
关键字:

session开启spring

spring 订阅