jwt判断token是否过期_SpringBootSecurity学习(13)前后端分离版之JWT

JWT 使用

前面简单介绍了把默认的页面登录改为前后端分离的接口异步登录的方法,可以帮我们实现基本的前后端分离登录功能。但是这种基本的登录和前面的页面登录还有一个一样的地方,就是使用session和cookie来维护登录状态,这种方法的问题在于,扩展性不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。

一种解决方案是 session 数据持久化,写入redis或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。

另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。关于JWT的理论知识,建议参考 阮一峰 大神写的教程 :http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html,这是我认为可能是写的最清晰的一个,下面的jwt的实现也是根据此教程来实现。

具体的理论知识可以参考教程,这里简单说下流程,用户登录成功后,在header中返回用户一个token信息,这个信息里面包含了加密的用户信息和数字签名,最重要的还有过期时间,客户端接到后,每次访问接口header中都带着这个token,服务端验证成功后就表示处于登录状态,过期后再从新获取即可。

具体的token内容包含了头部(加密信息),载体(用户信息),签名(签名两个部分的前面)三大块,三大块之间用英文句号(也就是 ".")连接起来,组成一个完整的token信息

流程设计

根据前面的理论知识,我们来设计一下如何使用jwt。首先我们使用jwt,就可以不再使用session和cookie,所以第一步就是:

  1. 在security配置文件中配置session为无状态。

然后考虑构建jwt消息体,有三个部分,第一个部分就是头部,内容是加密类型:

bc412abedeb6400cb1ba09493c69ee83

上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT,最后,将上面的 JSON 对象使用 Base64URL 算法转成字符串,作为第一部分。所以第二步就是:

  1. 在security配置文件中配置session为无状态。
  2. 确定header信息格式

下一步确定第二部分,消息载体(Payload),这也是一个json对象

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于 Spring Boot JWT Token 的前后分离问题,我可以为您提供一些帮助。 JWT(JSON Web Token)是一种基于 JSON 的开放标准(RFC 7519),用于在网络上安全传输声明。在前后分离的应用中,通常会使用 JWT 来实现用户认证和授权。 下面是一个简单的示例,演示了如何在 Spring Boot 应用中使用 JWT 和前后分离的方式进行用户认证。 首先,您需要在后应用中添加 JWT 相关的依赖。可以使用以下 Maven 依赖: ```xml <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> ``` 接下来,您需要编写一个 JWT 工具类,用于生成和验证 JWT。 ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.crypto.SecretKey; import java.util.Date; import java.util.HashMap; import java.util.Map; @Component public class JwtUtils { @Value("${jwt.secret}") private String secret; @Value("${jwt.expiration}") private Long expiration; private static final String CLAIM_KEY_USERNAME = "sub"; private static final String CLAIM_KEY_CREATED = "iat"; private SecretKey generateKey() { return Keys.hmacShaKeyFor(secret.getBytes()); } public String generateToken(String username) { Map<String, Object> claims = new HashMap<>(); claims.put(CLAIM_KEY_USERNAME, username); claims.put(CLAIM_KEY_CREATED, new Date()); return Jwts.builder() .setClaims(claims) .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000)) .signWith(generateKey(), SignatureAlgorithm.HS512) .compact(); } public Claims getClaimsFromToken(String token) { return Jwts.parserBuilder() .setSigningKey(generateKey()) .build() .parseClaimsJws(token) .getBody(); } public boolean isTokenExpired(String token) { Claims claims = getClaimsFromToken(token); Date expiration = claims.getExpiration(); return expiration.before(new Date()); } public boolean validateToken(String token, String username) { Claims claims = getClaimsFromToken(token); String subject = claims.getSubject(); Date expiration = claims.getExpiration(); return subject.equals(username) && !expiration.before(new Date()); } } ``` 在这个工具类中,我们使用了 io.jsonwebtoken 库来实现 JWT 的生成和验证。在生成 JWT 时,我们使用了一个密钥(secret)来签名 JWT。在验证 JWT 时,我们还检查了 JWT 中保存的用户名和过期时间是否正确。 接下来,您需要在 Spring Boot 应用中添加一个 JWT 认证过滤器,用于在请求到达后之前验证 JWT。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class JwtAuthenticationFilter extends OncePerRequestFilter { @Autowired private JwtUtils jwtUtils; @Autowired private UserDetailsService userDetailsService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String header = request.getHeader("Authorization"); if (header != null && header.startsWith("Bearer ")) { String token = header.substring(7); String username = jwtUtils.getClaimsFromToken(token).getSubject(); if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = userDetailsService.loadUserByUsername(username); if (jwtUtils.validateToken(token, username)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); } } } chain.doFilter(request, response); } } ``` 在这个过滤器中,我们从请求头中获取 JWT,然后使用之前编写的 JwtUtils 工具类来验证 JWT。如果 JWT 验证成功,则将用户信息添加到 Spring Security 的认证上下文中。 最后,在 Spring Boot 应用中添加一个登录接口,用于生成 JWT。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/auth") public class AuthController { @Autowired private AuthenticationManager authenticationManager; @Autowired private JwtUtils jwtUtils; @Autowired private UserDetailsService userDetailsService; @PostMapping("/login") public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) throws AuthenticationException { authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername()); String token = jwtUtils.generateToken(userDetails.getUsername()); Map<String, Object> response = new HashMap<>(); response.put("token", token); return ResponseEntity.ok(response); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } ``` 在这个登录接口中,我们首先使用 Spring Security 的 AuthenticationManager 来验证用户信息。如果验证成功,则使用 JwtUtils 工具类生成 JWT,并将 JWT 返回给前应用。 以上就是一个简单的 Spring Boot JWT Token 的前后分离示例。希望对您有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值