jwt
xxx.yyy.zzz -> header.payload.signature
1 2 3 4
| { "alg": "HS256", "typ": "JWT" }
|
header标记了使用的算法和token的类型
payload
1 2 3 4 5
| { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
|
payload中存放了一些数据,比如用户id、用户名等,还有一个iat
字段,表示token的签发时间
ps. payload中的数据不要存放敏感信息,因为payload是可以解码的
signature
1 2 3 4 5
| HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
|
signature是对header和payload的签名,防止数据被篡改,当服务端接收到token后,会重新计算一次签名,如果签名不一致,说明数据被篡改
两种使用方式
- 使用
java-jwt
库
1 2 3 4 5
| <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.14.0</version> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import com.auth0.jwt.JWT; import com.auth0.jwt.JWTCreator; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import java.util.Calendar; import java.util.Map; public class JWTUtils {
private static final String SING = "!Q@W#E$R";
public static String getToken(Map<String, String> map) { Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 120);
JWTCreator.Builder builder = JWT.create();
map.forEach((k, v) -> { builder.withClaim(k, v); }); String token = builder.withExpiresAt(instance.getTime()) .sign(Algorithm.HMAC256(SING)); return token; }
public static DecodedJWT verify(String token) { return JWT.require(Algorithm.HMAC256(SING)).build().verify(token); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import com.dunjia.jwtdemo.utils.JWTUtils; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import java.util.HashMap; import java.util.Map;
@Component public class JWTInterceptors implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { Map<String, Object> map = new HashMap<>(); String token = request.getHeader("token"); if (token != null && JWTUtils.verify(token) != null) { return true; } else { map.put("msg", "token无效,请重新登录!"); map.put("state", false); return false; } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import com.dunjia.jwtdemo.interceptor.JWTInterceptors; 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 InterceptorConfig implements WebMvcConfigurer {
@Autowired private JWTInterceptors jwtInterceptors;
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptors) .addPathPatterns("/user/**") .excludePathPatterns("/user/login"); } }
|
- 使用
jjwt
库
1 2 3 4 5
| <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; import java.util.UUID;
public class JwtUtil {
private static long time = 1000 * 60 * 60 * 24; private static String signature = "#@!$%^&*()";
public static String createToken() { JwtBuilder jwtBuilder = Jwts.builder(); String jwtToken = jwtBuilder .setHeaderParam("typ", "JWT") .setHeaderParam("alg", "HS256") .claim("username", "admin") .claim("password", "admin") .setSubject("jwt-token") .setExpiration(new Date(System.currentTimeMillis() + time)) .setId(UUID.randomUUID().toString()) .signWith(SignatureAlgorithm.HS256, signature) .compact(); return jwtToken; }
public static boolean verifyToken(String token) { if (token == null) { return false; } try { Jwts.parser().setSigningKey(signature).parseClaimsJws(token); } catch (Exception e) { return false; } return true; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor;
@Component public class JwtInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { if ("OPTIONS".equals(request.getMethod())) { return true; }
String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); if (JwtUtil.verifyToken(token)) { return true; } }
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import com.dunjia.back.utils.JwtInterceptor;
@Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private JwtInterceptor jwtInterceptor;
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/api/**") .excludePathPatterns( "/api/login", "/api/register", "/api/upload", "/image/**" ); } }
|