定义--看看就行了:=================================
JWT(JSON Web Token) 是一种开放标准(RFC 7519),用于在各方之间以 JSON 对象的形式安全地传输信息。
JWT 由三个部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
- Header:包含令牌类型(即 JWT)和签名算法(如 HMAC SHA256 或 RSA)。
- Payload:可以在里面存信息
- Signature:简单理解就是密码
使用场景:========================================
1.登录验证:
不做登陆验证的话,黑子如果知道你的url和请求参数,就可以直接通过浏览器或者postman之类的工具请求你的服务端,很危险,所以要验证这个请求是不是合法的。
流程:
生成令牌:登录时login请求是直接放进来的,然后用户名密码正确就可以生成令牌了,上面不是说可以在payload中存信息吗,生成令牌的过程中就可以将用户的信息存进去,爱放不放,放进去肯定有用。
存储令牌:令牌就是一字符串,没那么高大尚。login请求时后端将生成的令牌返回给前端,然后前端可以保存在浏览器的local storage中
携带令牌:以后在前端发起请求时都要将令牌作为请求头传给后端,可以在前端使用拦截器实现
验证令牌:后端在接收除login外的请求,都要先验证令牌,合法了我才让你请求我的服务(请求到后端的controller)
2.传递用户信息:
先不细说
实现:===========================================
1.引入jjwt依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2.创建jwt工具类--创不创其实无所谓,主要是更方便后面使用,为了优雅二字
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "yourSecretKey"; // 密钥--创建、解析令牌时要用
//生成jwt令牌
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 1 天有效期
.signWith(SignatureAlgorithm.HS256, SECRET_KEY) //签名算法
.compact();
}
//解析jwt令牌
public static boolean validateToken(String token) {
try {
Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token);
return true;
} catch (SignatureException | ExpiredJwtException | MalformedJwtException e) {
return false;
}
}
}
3.配置拦截器拦截用户请求进行jwt验证(使用过滤器也可以)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private JwtUtil jwtUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取到请求头中的令牌
String authorizationHeader = request.getHeader("Authorization");
//校验令牌是否合法
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
String token = authorizationHeader.substring(7);
if (jwtUtil.validateToken(token)) {
return true;
}
}
//返回不合法信息
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid or missing Authorization header");
return false;
}
}
4.注册并配置拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private JwtInterceptor jwtInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/login"); // 排除登录路径
}
}
5.在后端登录控制器中生成令牌并返回给前端
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public Map<String, String> login(@RequestBody AuthRequest authRequest) {
try {
//验证用户名密码是否正确
userMapper.......
//正确后进行下面步骤,否则直接返回
//生成令牌-username作为数据载荷部分
String token = jwtUtil.generateToken(authRequest.getUsername());
//将生成的令牌返回给前端
Map<String, String> response = new HashMap<>();
response.put("token", token);
return response;
} catch (AuthenticationException e) {
throw new RuntimeException("Invalid login credentials");
}
}
}
class AuthRequest {
private String username;
private String password;
// getters and setters
}
回顾整个流程:=====================================
用户首先进行登录==》
请求到后端controller==》
(用户名密码正确)生成令牌返回给前端==》
前端保存令牌并在以后每次请求中携带令牌
用户发起其他请求(请求头中携带了令牌)==》
后端拦截器拦截用户请求==》
解析请求中令牌是否合法==》
合法放行,不合法拒绝访问