JWT(전체 이름: Json Web Token)는 당사자 간에 정보를 JSON 개체로 안전하게 전송하는 간결하고 독립적인 방법을 정의하는 개방형 표준(RFC 7519)입니다.
각 사용자의 로그인 정보는 서버의 세션에 저장되며, 사용자 수가 늘어날수록 서버 오버헤드가 크게 늘어납니다.
세션 정보는 서버의 메모리에 저장되므로 분산 애플리케이션에 오류가 발생할 수 있습니다. 세션 정보가 Redis 캐시에 균일하게 저장될 수 있지만 이로 인해 복잡성이 증가할 수 있습니다.
세션 인증은 쿠키 기반이므로 비 브라우저 및 모바일 단말에서는 적용되지 않습니다.
프런트엔드와 백엔드 분리 시스템은 프런트엔드와 백엔드가 크로스 도메인이고, 쿠키 정보를 교차할 수 없기 때문에 세션 인증이 크로스 도메인 인증을 이어갈 수 없기 때문입니다.
간단함: JWT 토큰의 데이터 양은 적고 전송 속도도 매우 빠릅니다.
교차 언어: JWT 토큰은 JSON 암호화 형식으로 클라이언트에 저장되므로 JWT는 언어 간이며 모든 웹 양식에서 지원됩니다. 크로스 플랫폼: 쿠키와 세션에 의존하지 않으며 서버에 세션 정보를 저장할 필요가 없으며 분산 애플리케이션에 매우 적합하며 확장에 사용할 수 있습니다.
JWT의 첫 번째 부분은 일반적으로 아래와 같이 JWT 메타데이터를 설명하는 Json 객체인 헤더 부분입니다.
{ "alg": "HS256", "typ": "JWT" }
alg 속성은 서명에 사용되는 알고리즘을 나타내며, 기본값은 HMAC SHA256(HS256으로 작성됨)이고, typ 속성은 토큰 유형을 나타내며, JWT 토큰은 JWT로 일률적으로 작성됩니다.
JWT의 두 번째 부분은 Json 객체이기도 한 Payload입니다. 전달해야 하는 데이터를 포함하는 것 외에도 선택할 수 있는 7개의 기본 필드가 있습니다. iss: 발행자 exp: 만료 시간 sub: 제목 aud: 사용자 nbf: 이전에는 사용할 수 없음 iat: 릴리스 시간 jti: JWT ID는 이 JWT를 식별하는 데 사용됩니다
{ //默认字段 "sub":"主题123", //自定义字段 "name":"java", "isAdmin":"true", "loginTime":"2021-12-05 12:00:03" }
JWT는 기본적으로 암호화되지 않는다는 점에 유의하는 것이 중요합니다. 내용을 해독하므로 일부 민감한 정보가 여기에 저장되지 않은 경우 정보 유출을 방지할 수 있습니다. JSON 객체도 Base64 URL 알고리즘을 사용하여 문자열로 변환되어 저장됩니다.
서명 해시 부분은 위 두 부분의 데이터에 서명하는 것으로, base64로 인코딩된 헤더와 페이로드 데이터를 사용해야 하며, 데이터가 변조되지 않도록 지정된 알고리즘을 통해 해시를 생성해야 합니다.
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
public class JwtUtil { //创建jwt public static String createJWT(String subject, String issue, Object claim, long ttlMillis) { //当前时间 long nowMillis = System.currentTimeMillis(); //过期时间 long expireMillis = nowMillis + ttlMillis; String result = Jwts.builder() .setSubject(subject) //设置主题 .setIssuer(issue) //发行者 .setId(issue)//jwtID .setExpiration(new Date(expireMillis)) //设置过期日期 .claim("user", claim)//主题,可以包含用户信息 .signWith(getSignatureAlgorithm(), getSignedKey())//加密算法 .compressWith(CompressionCodecs.DEFLATE).compact();//对载荷进行压缩 return result; } // 解析jwt public static Jws<Claims> pareseJWT(String jwt) { Jws<Claims> claims; try { claims = Jwts.parser().setSigningKey(getSignedKey()) .parseClaimsJws(jwt); } catch (Exception ex) { claims = null; } return claims; } //获取主题信息 public static Claims getClaims(String jwt) { Claims claims; try { claims = Jwts.parser().setSigningKey(getSignedKey()) .parseClaimsJws(jwt).getBody(); } catch (Exception ex) { claims = null; } return claims; } } /** * 获取密钥 * * @return Key */ private static Key getSignedKey() { byte[] apiKeySecretBytes = DatatypeConverter .parseBase64Binary(getAuthKey()); Key signingKey = new SecretKeySpec(apiKeySecretBytes, getSignatureAlgorithm().getJcaName()); return signingKey; } private static SignatureAlgorithm getSignatureAlgorithm() { return SignatureAlgorithm.HS256; } //获取密钥,可以动态配置 public static String getAuthKey() { String auth = "123@#1234"; }
Component public class TokenInterceptor extends HandlerInterceptorAdapter { public static Log logger = LogManager.getLogger(TokenInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String uri = request.getRequestURI(); logger.info("start TokenInterceptor preHandle.." + uri); //需要过滤特殊请求 if (SystemUtil.isFree(uri) || SystemUtil.isProtected(uri)) { return true; } String metohd=request.getMethod().toString(); logger.info("TokenInterceptor request method:"+metohd); //options 方法需要过滤 if("OPTIONS".equals(metohd)) { return true; } //是否开启token认证 boolean flag = SystemUtil.getVerifyToken(); ResponseResult result = new ResponseResult(); //从请求的head信息中获取token String token = request.getHeader("X-Token"); if (flag) { if(StringUtils.isEmpty(token)) { token=request.getParameter("X-Token"); } // token不存在 if (StringUtils.isEmpty(token)) { result.setCode(ResultCode.NEED_AUTH.getCode()); result.setMsg(ResultCode.NEED_AUTH.getMsg()); WebUtil.writeJson(result, response); return false; } else { Claims claims = JwtUtil.getClaims(token); String subject = ""; if (claims != null) { subject = claims.getSubject(); // 验证主题 if (StringUtils.isEmpty(subject)) { result.setCode(ResultCode.INVALID_TOKEN.getCode()); result.setMsg(ResultCode.INVALID_TOKEN.getMsg()); WebUtil.writeJson(result, response); return false; } } else { result.setCode(ResultCode.INVALID_TOKEN.getCode()); result.setMsg(ResultCode.INVALID_TOKEN.getMsg()); WebUtil.writeJson(result, response); return false; } } } return true; } }
@Configuration public class WebConfig implements WebMvcConfigurer { @Resource private TokenInterceptor tokenInterceptor; public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(tokenInterceptor).addPathPatterns("/**"); } }
위 내용은 Spring Boot는 프런트엔드 및 백엔드 인증을 달성하기 위해 JWT를 어떻게 통합합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!