【Redis 与 JWT 实现session分布式 区别】

区别

Redis和JWT都可以用于实现分布式Session,但它们之间的实现方式和应用场景有所不同

Redis作为一个内存数据库,支持快速存储和读取Session数据,通常用于Session集中管理,实现Session的共享和持久化。Spring Session框架就是基于Redis的Session管理解决方案之一。

通过将Session数据存储在Redis中,就可以在多个服务器之间共享Session数据,实现Session的分布式管理。同时,Redis提供了高效的Session读写、查询、过期和删除等操作,可以帮助我们更好地管理Session数据,有效地减少Session的内存消耗。

而JWT是一种基于Token的身份验证和授权机制,通常用于实现无状态Session,即客户端在每次请求时传递一个Token,服务器根据这个Token进行验证和授权,不需要保存任何Session信息。

JWT通常适用于多个独立的服务之间进行鉴权和授权,不需要共享Session信息的场景。它的实现方式是将用户的身份信息放入Token中,通过签名和验证来保证Token的可靠性。

总结来说,Redis适用于需要共享Session数据的分布式场景,而JWT适用于需要跨服务进行身份验证和授权的场景。根据实际的应用场景,我们可以选择不同的Session管理解决方案。

若没有使用redis存储,默认是以什么形式存在,怎么存储的

如果没有使用Redis存储Session,则Spring会默认使用Servlet容器提供的Session机制进行存储。

在Servlet容器中,Session数据是将其存储在服务器的内存中,也称为内存Session。Servlet容器可以为每个Session对象分配一个唯一的Session ID,并且该Session ID也作为URL重写和Cookie传递参数使用,以便于在服务器和客户端之间进行传递。

当客户端向服务器发送请求时,服务器会根据Session ID查询相应的Session对象,获取其中存储的信息,以实现Session的持久化和共享。

需要注意的是,由于内存Session是存储在服务器内存中的,因此在高并发场景下容易出现内存消耗过大的问题。因此,当应用需要处理大量的并发Session时,建议使用分布式Session存储方案,如Redis等。

为什么JWT比较适合于邮箱激活场景

JWT(JSON Web Token)是一种基于 JSON 的开放标准(RFC 7519),用于在网络上传输声明。通常用于身份验证和授权。JWT 由三部分组成,分别是头部、载荷和签名,其中头部和载荷都是明文的,签名是用于验证身份的密文。

在邮箱激活方面,JWT 是一种更好的选择,因为:

  1. 独立与前后端的状态管理

JWT 是一种独立于前后端的状态管理方式,可以在后端生成 JWT 并将其发放给前端,前端可以在之后的操作中将 JWT 发送给后端进行验证。由于 JWT 包含全部必要的信息,因此可以避免使用其他技术(例如 Session)时的状态管理问题,使开发更加简单。

  1. 可以防止 CSRF 攻击

对于使用 Session 进行状态管理的站点,很容易受到 CSRF 攻击,而 JWT 可以使用 CSRF Token 进行保护。

  1. 可以通过集成OAuth2来实现更高级别的安全性

JWT 可以作为 OAuth2 协议中的一个关键部件,为应用程序提供更高级别的安全性。OAuth2 的授权服务器可以生成 JWT 并将其发放给客户端,客户端可以使用 JWT 进行身份验证和授权。

适合使用JWT的场景:有效期短,只希望被使用一次
比如,用户注册后发一封邮件让其激活账户,通常邮件中需要有一个链接,这个链接需要具备以下的特性:能够标识用户,该链接具有时效性(通常只允许几小时之内激活),不能被篡改以激活其他可能的账户,一次性的。这种场景就适合使用jwt。

而由于JWT具有一次性的特性。单点登录和会话管理非常不适合用JWT ,如果在服务端部署额外的逻辑存储JWT 的状态,那还不如使用session。基于session有很多成熟的框架可以开箱即用,但是用JWT 还要自己实现逻辑。
因此,使用 JWT 可以更好地实现邮箱激活的安全性、可扩展性和可维护性,这是一种更好的选择。

springboot整合JWT

在 Spring Boot 项目中实现 JWT 的过程可以分为两个步骤,第一步是生成 JWT,在用户登录后将生成的 JWT 发送给客户端;第二步是在客户端请求时,将 JWT 发送给后端,后端对 JWT 进行验证,如果验证通过则说明用户已经登录,否则需要重新登录。

下面是在 Spring Boot 中实现 JWT,以实现登录态储存为例:

  1. 添加依赖

pom.xml 中添加以下依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
  1. 生成 JWT

在用户登录成功后,可以使用以下代码生成 JWT 并返回给客户端:

// 导入所需的类
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;

// 生成 JWT 的方法
private String generateJWT(String username) {
    // 设置过期时间为一小时
    Date expireDate = new Date(System.currentTimeMillis() + 60 * 60 * 1000);
    // 使用 JWT 组件生成 JWT
    String jwt = Jwts.builder()
            .setSubject(username)  // Payload 中写入用户名
            .setExpiration(expireDate)  // 设置过期时间
            .signWith(SignatureAlgorithm.HS512, "secret")  // 加密方式以及秘钥
            .compact();
    return jwt;  // 返回生成的 JWT
}
  1. 验证 JWT

在客户端发送请求时,需要将 JWT 发送到后端进行验证,验证代码如下:

// 导入所需的类
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;
import org.springframework.web.filter.OncePerRequestFilter;

public class JwtFilter extends OncePerRequestFilter {
    private static final String SECRET = "secret";  // JWT 秘钥

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String header = request.getHeader("Authorization");  // 从请求头获取 JWT
        if (header == null || !header.startsWith("Bearer ")) {  // 判断 JWT 是否存在
            // JWT 不存在
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }

        String token = header.split(" ")[1];  // 获取 JWT Token
        try {
            Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
            // 验证 JWT 是否过期
            if (claims.getExpiration().before(new Date())) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                return;
            }
            // 将用户信息储存起来,这里以 username 为例
            request.setAttribute("username", claims.getSubject());
            // 让请求继续传递
            filterChain.doFilter(request, response);
        } catch (SignatureException e) {
            // JWT 不合法
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
    }
}
  1. 储存登录态

在 JWT 身份验证通过后,可以将用户的登录态储存到 Session 中。可以使用以下代码实现:

// 导入所需的类
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

// 在 Spring Boot 中获取当前用户信息的方法
private Authentication getCurrentAuthentication() {
    return SecurityContextHolder.getContext().getAuthentication();
}

// 获取当前登录的用户名
private String getCurrentUsername() {
    Authentication authentication = getCurrentAuthentication();
    return authentication == null ? null : authentication.getName();
}

// 将用户登录信息储存到 Session 中
private void storeUserInformationInSession(HttpServletRequest request) {
    String username = getCurrentUsername();
    request.getSession(true).setAttribute("username", username);
}

这样,就实现了在 Spring Boot 项目中使用 JWT 的登录态储存功能。需要注意的是,还需要在登录界面添加 JWT 的传递并在拦截器中进行身份验证,以达到整个项目都使用 JWT 进行身份验证的效果。

springboot整合redis

在Spring Boot中,通过整合Spring Session和Redis来实现分布式Session非常简单。具体实现步骤如下:

  1. 在pom.xml中加入下面的依赖
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
  1. 在application.properties文件中配置Redis连接参数
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
  1. 创建一个配置类,用于配置Spring Session和Redis
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) // Session过期时间为30分钟
public class SessionConfig {
}
  1. 在Controller中使用Session
@RestController
public class MyController {
    
    @GetMapping("/testSession")
    public String testSession(HttpServletRequest request) {
        HttpSession session = request.getSession();
        session.setAttribute("key", "value");
        return "Session已设置";
    }
    
    @GetMapping("/getSession")
    public String getSession(HttpServletRequest request) {
        HttpSession session = request.getSession();
        String value = (String) session.getAttribute("key");
        return "Session中的值为:" + value;
    }
}

以上就是通过Spring Session和Redis实现分布式Session的步骤。注意,在这个例子中,当使用request.getSession()时,会默认创建一个新的Session或者返回已经存在的Session,而不是使用默认的Cookie-based实现方式。然后,我们可以使用Session中的setAttribute()getAttribute()方法来存储和读取Session中的数据。在这里,通过使用Redis,我们可以确保Session的数据能够被多个服务器共享,这就是分布式Session的作用。

session如何存储在redis中

在Spring Boot中,Spring Session通过使用Redis来存储Session的数据。在Redis中,Session的数据是以Key-Value的形式进行存储,其中Key是一个唯一的Session ID,Value则是Session中包含的所有信息,如Session的创建时间、最后访问时间、Session属性等。具体实现步骤如下:

  1. 配置Redis连接参数,如下所示:
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
  1. spring-session-data-redis包添加到你项目的依赖中,如下所示:
<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session-data-redis</artifactId>
	<version>2.1.9.RELEASE</version>
</dependency>
  1. 在你的Spring Boot配置文件中通过@EnableRedisHttpSession注解来启用Spring Session并设置Session的过期时间(单位:秒),如下所示:
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)
public class RedisSessionConfig {
}
  1. 完成以上配置后,当你使用Session时,Spring会将Session中的数据存储在Redis中,Key为Session ID,Value为Session的所有数据。这样就可以实现仿佛在单个服务器上一样地处理Session,但实际上Session的数据已经存储在了集群中的所有服务器上。

进一步地,你可以使用redis-cli命令行来检查Redis中存储的Session信息。例如,你可以运行以下命令来检查Redis中所有的Key:

$ redis-cli
127.0.0.1:6379> KEYS *
1) "spring:session:sessions:bde08356-21b5-4795-bf8b-7ccd12d30c19"

可以看到,存在一个spring:session:sessions前缀的Key,这个前缀是Spring Session框架中默认的Key前缀,用于存储Session ID。你也可以通过命令对Session信息进行存储、获取、更新等操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值