前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >spring之session

spring之session

作者头像
叔牙
发布2020-11-19 17:42:20
发布2020-11-19 17:42:20
6500
举报

spring之session

1概述

Spring Session的目标是从存储在服务器中的HTTP会话的限制中释放会话管理。

该解决方案可以轻松地在独立部署的服务之间共享会话数据,而不必绑定到单个容器(即Tomcat)。 此外,它支持在同一浏览器中的多个会话并在标头中发送会话。

在本文中,我们将使用Spring Session来管理Web应用程序中的身份验证信息。 虽然Spring Session可以使用JDBC或MongoDB来持久保存数据,但我们将使用Redis。

2简单项目案例

首先创建一个简单的Spring Boot项目,方便在后边的会话示例中使用:

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.0.5.RELEASE</version>
  5. <relativePath/>
  6. </parent>
  7. <dependencies>
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-security</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-web</artifactId>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework.boot</groupId>
  18. <artifactId>spring-boot-starter-test</artifactId>
  19. <scope>test</scope>
  20. </dependency>
  21. </dependencies>

我们的应用程序使用Spring Boot运行,父pom为每个条目提供版本。 可以在Maven中心仓库找到每个依赖项的最新版本。

还需要在application.properties中为我们的Redis服务器添加一些配置属性:

  1. spring.redis.database=0
  2. spring.redis.host=host
  3. spring.redis.port=6379
  4. spring.redis.password=password

3springboot配置

首先,演示使用Boot配置Spring Session。

注意:不需要完成第3节和第4节。只需选择一个,具体取决于您是否使用SpringBoot配置Spring Session。

3.1:依赖管理

添加以下依赖到我们的项目中:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.session</groupId>
  7. <artifactId>spring-session</artifactId>
  8. </dependency>

我们使用启动父pom在这里设置版本,因此这些版本可以保证与我们的其他依赖项一起使用。

3.2:Spring会话配置

现在为Spring Session添加一个配置类:

  1. @Configuration
  2. @EnableRedisHttpSession
  3. public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
  4. }

4标准spring配置(不使用springboot)

我们看一下不使用Spring Boot,使用传统方式实现spring集成和配置spring-session。

4.1:依赖管理

首先,如果我们将spring-session添加到标准的Spring项目中,我们需要明确定义:

  1. <dependency>
  2. <groupId>org.springframework.session</groupId>
  3. <artifactId>spring-session</artifactId>
  4. <version>1.2.2.RELEASE</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.data</groupId>
  8. <artifactId>spring-data-redis</artifactId>
  9. <version>2.0.5.RELEASE</version>
  10. </dependency>

4.2:spring session配置

现在为Spring Session添加一个配置类:

  1. @Configuration
  2. @EnableRedisHttpSession
  3. public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
  4. @Bean
  5. public JedisConnectionFactory connectionFactory() {
  6. return new JedisConnectionFactory();
  7. }
  8. }

正如你所看到的最小差异-我们现在必须明确定义JedisConnectionFactory bean,而SpringBoot帮我们做了。

在两种类型中,@EnableRedisHttpSession和AbstractHttpSessionApplicationInitializer的扩展实现,将在所有安全基础结构之前创建并连接一个过滤器,

用以查找活跃会话,并用存储在Redis中的值来填充安全上下文。

接下来我们用控制器和安全配置来完成这个应用程序。

5应用配置

添加一个控制器:

  1. @RestController
  2. public class SessionController {
  3. @RequestMapping("/")
  4. public String helloAdmin() {
  5. return "hello admin";
  6. }
  7. }

这个控制器为我们提供一个测试端点。

接下来,添加我们的安全配置类:

  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Autowired
  5. public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  6. auth
  7. .inMemoryAuthentication()
  8. .withUser("admin").password("password").roles("ADMIN");
  9. }
  10. @Override
  11. protected void configure(HttpSecurity http) throws Exception {
  12. http
  13. .httpBasic().and()
  14. .authorizeRequests()
  15. .antMatchers("/").hasRole("ADMIN")
  16. .anyRequest().authenticated();
  17. }
  18. }

这可以通过基本身份验证保护我们的端点,并设置要测试的用户。

6测试

最后,对上述内容进行测试,我们将在这里定义一个简单的测试,这将允许我们做两件事:

  • 使用实时Web应用程序
  • 与Redis交互

测试准备:

  1. public class SessionControllerTest {
  2. private Jedis jedis;
  3. private TestRestTemplate testRestTemplate;
  4. private TestRestTemplate testRestTemplateWithAuth;
  5. private String testUrl = "http://localhost:8080/";
  6. @Before
  7. public void clearRedisData() {
  8. testRestTemplate = new TestRestTemplate();
  9. testRestTemplateWithAuth = new TestRestTemplate("admin", "password", null);
  10. jedis = new Jedis("host", 6379);
  11. jedis.flushAll();
  12. }
  13. }

需要注意的是,我们如何设置这两个客户端-HTTP客户端和Redis客户端。 当然,此时服务器(和Redis)应该启动并运行-这样我们就可以通过这些测试与它们进行通信。

从测试Redis是空的开始:

  1. @Test
  2. public void testRedisIsEmpty() {
  3. Set<String> result = jedis.keys("*");
  4. assertEquals(0, result.size());
  5. }

现在测试我们的安全保护为未经身份验证的请求返回401:

  1. @Test
  2. public void testUnauthenticatedCantAccess() {
  3. ResponseEntity<String> result = testRestTemplate.getForEntity(testUrl, String.class);
  4. assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
  5. }

接下来,我们测试Spring Session是否在管理我们的身份验证令牌:

  1. @Test
  2. public void testRedisControlsSession() {
  3. ResponseEntity<String> result = testRestTemplateWithAuth.getForEntity(testUrl, String.class);
  4. assertEquals("hello admin", result.getBody()); //login worked
  5. Set<String> redisResult = jedis.keys("*");
  6. assertTrue(redisResult.size() > 0); //redis is populated with session data
  7. String sessionCookie = result.getHeaders().get("Set-Cookie").get(0).split(";")[0];
  8. HttpHeaders headers = new HttpHeaders();
  9. headers.add("Cookie", sessionCookie);
  10. HttpEntity<String> httpEntity = new HttpEntity<>(headers);
  11. result = testRestTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, String.class);
  12. assertEquals("hello admin", result.getBody()); //access with session works worked
  13. jedis.flushAll(); //clear all keys in redis
  14. result = testRestTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, String.class);
  15. assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
  16. //access denied after sessions are removed in redis
  17. }

首先,我们的测试使用管理员身份验证凭据确认我们的请求成功。

然后我们从响应头中提取会话值,并在第二个请求中将其用作我们的身份验证。 验证之后清除Redis中的所有数据。

最后,我们使用会话cookie发出另一个请求并确认已注销。 这证实了Spring Session正在管理我们的会话。

总结

Spring Session是一个用于管理HTTP会话的强大工具。 通过将会话存储简化为配置类和几个Maven依赖项,我们现在可以将多个应用程序连接到同一个Redis实例并共享身份验证信息。

比如为了应对高并发请求,应用集群部署,那么应用的多个部署实例可以共享同一份session信息。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PersistentCoder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1概述
  • 2简单项目案例
  • 3springboot配置
  • 4标准spring配置(不使用springboot)
  • 5应用配置
  • 6测试
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档