十六.SpringCloud+SpringSession实现微服务单点登录

简介: SpringCloud+SpringSession实现微服务单点登录

Session不共享问题

对于登录而言,通常情况下我们喜欢把登录信息存储到服务器的Session中,这种存储方式在单体应用中没有问题,但是在分布式/集群环境中会存在Session丢失问题,如下图:
image.png

解决方案也有很多,在《微服务认证授权方案》一文中有相关的解决方案分析,这里不在重复赘述,本文章的目的是使用SpringSession+Redis来解决分布式系统中的单点登问题

SpringSession的认证方案

这种认证方案还是使用的是session,只不过是将Session统一存储到Redis中实现session共享,各个服务可以从Redis中获取Session得到认证信息,然后做身份检查,权限校验等工作,当然整个流程我们可以自己实现,但是如何把session存储到Redis以及从Redis中取出Session是一个麻烦的事情,Spring提供了解决方案SpringSession
image.png

SpringSession干的工作就是修改getSession和setSession方法基于Redis存取Session,同时要注意的是Session是通过Cookie传递sessionid的,如果要让多个服务都能接受到sessionid拿到session,需要把cookie的存储域扩大,如有三个系统“auth.mall.com”,"goods.maill.com","stock.mall.com",那我们需要把domian设置成“mall.com”,这样一来浏览器带着cookie请求任何一个系统都可以获取到sessionid,然后从Redis中获取Session。

ps:如果您还不知道session和cookie的执行流程,请先去查查资料

SpringSession入门

官网文档在这

这里我们使用SpringBoot应用为例,我们需要导入spring-session-data-redis依赖,Spring Boot 会自动创建了一个名为springSessionRepositoryFilter的Filter,它负责更换原生的HttpSession为自定义实现,比如基于Redis实现

1.搭建项目,集成SpringSession

这里是以SpringBoot为例,你需要搭建一个SpringBoot的应用,然后导入SpringSession整合Redis的依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>
    <dependencies>
         <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
              <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

data-redis默认基于lettuce实现,我这里更换成了jedis

2.配置SpringSession存储方式

然后把session配置存储类型为Redis,以及配置Redis链接信息

#server.servlet.session.timeout =#会话超时。如果未指定持续时间后缀,则使用秒。
spring:
  session:
    store-type: redis
  redis:
    host: localhost
    port: 6379
    # 选择redis的数据库的分库
    database: 0
    password: 123456
    #redis连接池配置
    jedis:
      pool:
        max-idle: 10
        min-idle: 5
        max-active: 100
        max-wait: 3000
        timeout: 6005

3.SpringSession的Java配置

最后编写SpringSesson配置类,通过@EnableRedisHttpSession 注解开启SpringSession ,通过该注解,SpringSession会创建一个Servlet过滤器,该过滤器用Spring 定义的Session替换HttpSession 实现Redis存储。

//开启SpringSession,基于Redis存储,maxInactiveIntervalInSeconds是session失效时间
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=1800)
public class SpringSessionConfig {
   
   

}

注意:该配置类需要被@SpringBootApplication扫描到

4.Session存储实体类测试

实体类,需要实现Serializable接口

public class VipUser implements Serializable  {
   
   
     private Long id;
     private String password;
     private String nickName;
     ...省略...
}

使用sesson存取一个User对象

@RestController
public class LoginController {
   
   

    @RequestMapping("/login")
    public void login(HttpSession session){
   
   
        VipUser user = new VipUser();
        user.setId(1L);
        user.setNickName("王大锤");
        user.setPassword("123456");
        String key = "user";
        //添加属性到Session
        session.setAttribute(key,user);
        //从sesson中取出属性值
        VipUser userFromSession = (VipUser)session.getAttribute(key);

        System.out.println(userFromSession.getId()+" , "+userFromSession.getNickName()+" , "+userFromSession.getPassword());
    }
}

上面的代码很简单,使用session存储一个user , 启动好Redis服务器,使用Postmain访问 /login ,观察Redis中的数据
image.png

Redis效果如下:

image.png

看到这个效果,说明session确实存储到了Redis,并且可以正常的完成存取操作。

SpringSession的自定义配置

1.定义Redis序列化方式

SpringSession把值存储到Redis中默认情况下使用的是JDK的序列化方式,它要求我们存储的实体类需要实现Serializable接口,我们希望Redis以一种更友好更通用的方式去存储数据,即:JSON,我们可以通过定义序列化器来实现JSON方式的数据存储

//开启SpringSession,基于Redis存储,maxInactiveIntervalInSeconds是session失效时间
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=1800)
public class SpringSessionConfig {
   
   

    /**
     * 更换序列化器,使用JSON的序列化器
     */
    //@Bean("springSessionDefaultRedisSerializer")
    public RedisSerializer setSerializer(){
   
   
        return new GenericJackson2JsonRedisSerializer();
    }
}

2.定义cookie的序列化器

在前面我们讨论过,在分布式环境中,一个系统由多个子系统组成,如果要实现单点登录就要实现cookie跨域共享,否则在不同的子系统中是获取不到Session的,我们可以通过设置cookie的domain来扩大cookie的作用域,比如:有三个子系统分别是“auth.mall.com”,“goods.mall.com”,“stock.mall.com”,那么我们把cookie的domain设置为“mall.com”,那三个子系统就都可以获取到cookie,从而三个子系统都可以获取到相同的session了。

定义CookieSerializer 序列化器,如下:

//开启SpringSession,基于Redis存储,maxInactiveIntervalInSeconds是session失效时间
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=1800)
public class SpringSessionConfig {
   
   

    /**
     * 更换序列化器
     */
    //@Bean("springSessionDefaultRedisSerializer")
    public RedisSerializer setSerializer(){
   
   
        return new GenericJackson2JsonRedisSerializer();
    }

    /**
     * 设置cookie域
     */

    @Bean
    public CookieSerializer cookieSerializer(){
   
   
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        //cookieSerializer.setCookieMaxAge();
        cookieSerializer.setCookieName("mysession");    //cookie的名字
        cookieSerializer.setDomainName("mall.com");        //cookie的域
        cookieSerializer.setUseHttpOnlyCookie(false);    //只是支持http
        return cookieSerializer;
    }
}

3.测试

image.png

文章结束,最后附上一张相对完整的分布式应用登录的流程图,希望对你有所帮助
image.png

相关文章
|
6月前
|
算法 Java 微服务
【SpringCloud(1)】初识微服务架构:创建一个简单的微服务;java与Spring与微服务;初入RestTemplate
微服务架构是What?? 微服务架构是一种架构模式,它提出将单一应用程序划分为一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。 每个服务允许在其独立的进程中,服务于服务间采用轻量级的通信机制互相协作(通常是Http协议的RESTful API或RPC协议)。 每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据上下文,选择合适的语言、工具对其进行构建
650 126
|
6月前
|
负载均衡 算法 Java
【SpringCloud(2)】微服务注册中心:Eureka、Zookeeper;CAP分析;服务注册与服务发现;单机/集群部署Eureka;连接注册中心
1. 什么是服务治理? SpringCloud封装了Netfix开发的Eureka模块来实现服务治理 在传统pc的远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册
417 0
|
6月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
7月前
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
470 1
|
7月前
|
jenkins Java 持续交付
使用 Jenkins 和 Spring Cloud 自动化微服务部署
随着单体应用逐渐被微服务架构取代,企业对快速发布、可扩展性和高可用性的需求日益增长。Jenkins 作为领先的持续集成与部署工具,结合 Spring Cloud 提供的云原生解决方案,能够有效简化微服务的开发、测试与部署流程。本文介绍了如何通过 Jenkins 实现微服务的自动化构建与部署,并结合 Spring Cloud 的配置管理、服务发现等功能,打造高效、稳定的微服务交付流程。
918 0
使用 Jenkins 和 Spring Cloud 自动化微服务部署
|
7月前
|
Kubernetes Java 微服务
Spring Cloud 微服务架构技术解析与实践指南
本文档全面介绍 Spring Cloud 微服务架构的核心组件、设计理念和实现方案。作为构建分布式系统的综合工具箱,Spring Cloud 为微服务架构提供了服务发现、配置管理、负载均衡、熔断器等关键功能的标准化实现。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
665 0
|
SpringCloudAlibaba API 开发者
新版-SpringCloud+SpringCloud Alibaba
新版-SpringCloud+SpringCloud Alibaba
|
负载均衡 Dubbo Java
Spring Cloud Alibaba与Spring Cloud区别和联系?
Spring Cloud Alibaba与Spring Cloud区别和联系?
|
人工智能 SpringCloudAlibaba 自然语言处理
SpringCloud Alibaba AI整合DeepSeek落地AI项目实战
在现代软件开发领域,微服务架构因其灵活性、可扩展性和模块化特性而受到广泛欢迎。微服务架构通过将大型应用程序拆分为多个小型、独立的服务,每个服务运行在其独立的进程中,服务与服务间通过轻量级通信机制(通常是HTTP API)进行通信。这种架构模式有助于提升系统的可维护性、可扩展性和开发效率。
5102 2

热门文章

最新文章