JSON Web Tokens 의 실현 원리
최근 에 Python 프로젝트 의 개 조 를 하고 python 프로젝트 를 자바 프로젝트 로 재 구성 하 는 과정 에서 이 지식 을 만 났 습 니 다.이것 은 매우 실 용적 이 라 고 생각 하기 때문에 퇴근 후에 돌아 와 서 쇠뿔 도 단 김 에 이 정 리 를 쓰 고 뒤에 있 는 사람들 이 참고 하여 시행 착 오 를 적 게 걷 기 를 바 랍 니 다.
1.우위 소개
JSON Web Tokens 는 jwt 라 고 부 르 며 rest 인터페이스의 안전 전략 입 니 다.그 자체 에 많은 장점 이 있다.
크로스 도 메 인 문제 해결:이러한 Token 기반 방문 전략 은 cookies 의 크로스 도 메 인 문 제 를 극복 할 수 있 습 니 다.
서버 가 상태 가 없 으 면 가로로 확장 할 수 있 고 Token 은 인증 을 완료 할 수 있 으 며 Session 을 저장 할 필요 가 없습니다.
시스템 디 버 깅,Token 은 모든 사용자 정 보 를 가지 고 있 습 니 다.특정한 인증 방안 을 연결 하지 않 고 암호 화 방법 과 키 만 알 면 암호 화 디 버 깅 을 할 수 있어 디 버 깅 에 유리 합 니 다.
크로스 사이트 스 크 립 트 공격 을 방지 하고 쿠키 기술 이 없 으 며 크로스 사이트 요청 의 안전 문 제 를 고려 할 필요 가 없습니다.
원리 소개
JSON Web Tokens 의 형식 으로 구성 되 어 있 습 니 다.jwt 는 base 64 에 인 코딩 된 문자 시퀀스 로 점 번호 로 구분 되 어 있 으 며 모두 세 부분 으로 구성 되 어 있 습 니 다.머리 header,메시지 체 play load 와 서명 sign 입 니 다.
1.jwt 의 머리 Header 는 json 형식 입 니 다.
{
"typ":"JWT",
"alg":"HS256",
"exp":1491066992916
}
그 중에서 typ 는 type 의 약자 로 이 유형 은 JWT 형식 이 고 암호 화 방식 은 HS 256 이 며 exp 는 현재 시간 을 대표 합 니 다.2.jwt 메시지 체 Playload
{
"userid":"123456",
"iss":"companyName"
}
메시지 체 의 구체 적 인 필드 는 업무 수요 에 따라 자체 적 으로 정의 하고 추가 할 수 있 으 며,복호화 할 때 필드 의 key 값 으로 value 를 가 져 오 는 것 에 주의 하 십시오.3.서명 sign 생 성
마지막 으로 서명 입 니 다.서명 의 생 성 은 header 와 playload 를 각각 base64url 인 코딩 을 사용 한 다음'.'두 인 코딩 된 문자열 을 연결 한 다음 에 이 연 결 된 문자열 을 키 에 맞 춰 HMAC SHA-256 알고리즘 을 암호 화하 고 마지막 으로 base 64 인 코딩 을 다시 합 니 다.이것 은 서명 sign 을 받 았 습 니 다.마지막 으로 header 와 playload 와 sign 을'연결 하면 전체 JWT 가 생 성 됩 니 다.
3.검사 안내
전체 jwt 의 구 조 는 header.playload.sign 연결 로 구성 되 어 있 으 며,sign 만 키 로 암호 화 되 어 있 으 며,모든 정 보 는 header 와 playload 에서 직접 얻 을 수 있 습 니 다.sign 의 역할 은 header 와 playload 의 정보 가 변경 되 었 는 지 검증 하 는 것 이기 때문에 jwt 는 수 거 를 보호 할 수 없 지만,이상 의 특성 은 권한 인증 에 잘 적 용 될 수 있 습 니 다.
1.암호 화
예 를 들 어 암호 화 검증 할 것 은 userid 필드 입 니 다.먼저 json 메시지 헤더 헤더 와 메시지 체 playload 를 앞의 형식 으로 조립 하고 header.playload 에 따라 문자열 을 구성 한 다음 키 와 HS 256 암호 헤더.playload 에 따라 sign 서명 을 받 고 마지막 으로 jwtToken 을 header.playload.sign 으로 받 습 니 다.http 요청 중의 url 에 인 자 를 가지 고 백 엔 드 서비스 에 인증 을 요청 합 니 다.
2.복호화
백 엔 드 서 비 스 는 jwtToken 이 인터페이스 서 비 스 를 방문 할 권리 가 있 는 지 확인 하고 복호화 인증 을 할 수 있 습 니 다.예 를 들 어 방문 자의 userid 를 검사 할 수 있 습 니 다.먼저
문자열 을.번호 에 따라 세 개의 문자열 로 나 누 어 각각 header 와 playload,sign 을 얻 습 니 다.그 다음 에 header.playload 조합 을 키 와 HAMC SHA-256 알고리즘 으로 암호 화한 다음 에 새로운 문자열 과 sign 을 비교 합 니 다.똑 같 으 면 데이터 가 변경 되 지 않 았 다 는 뜻 입 니 다.그리고 머리 에서 exp 를 꺼 내 생존 기간 을 판단 하고 생존 기간 을 초과 하면 빈 문자열 로 돌아 갑 니 다.생존 기간 내 에 userid 의 값 을 되 돌려 줍 니 다.
코드 예제
1.python 코드 의 암호 화 복호화
#!/usr/bin/env python
# coding: utf-8
from itsdangerous import BadTimeSignature, SignatureExpired
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
APP_SECRET_KEY="secret"
MAX_TOKEN_AGE=1800
token_generator = Serializer(APP_SECRET_KEY, expires_in=MAX_TOKEN_AGE)
def generate_auth_token(userid):
access_token = token_generator.dumps({"userid":userid})
return access_token
def verify_token(token):
try:
user_auth = token_generator.loads(token)
print type(token_generator)
except SignatureExpired as e:
raise e
except BadTimeSignature as e:
raise e
return user_auth
2.자바 코드 의 암호 화 복호화
package api.test.util;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
/**
* jwt
*
* @author zhengsc
*/
@Slf4j
public class TokenUtil {
private String ISSUER = "companyName"; //
private String APP_SECRET_KEY = "secret"; //
private long MAX_TOKEN_AGE = 1800; //
/**
* userId accessToken
*
* @param userid
* @return
*/
public String generateAccessToken(String userid) {
JSONObject claims = new JSONObject();
claims.put("iss", ISSUER);
claims.put("userid", userid);
String accessToken = sign(claims, APP_SECRET_KEY);
return accessToken;
}
/**
* userid
*
* @param token
* @return
*/
public String verifyToken(String token) {
String userid = "";
try {
String[] splitStr = token.split("\\.");
String headerAndClaimsStr = splitStr[0] + "." +splitStr[1];
String veryStr = signHmac256(headerAndClaimsStr, APP_SECRET_KEY);
//
if (veryStr.equals(splitStr[2])) {
String header = new String(Base64.decodeBase64(splitStr[0]),"UTF-8");
JSONObject head = JSONObject.fromObject(header);
long expire = head.getLong("exp") * 1000L;
long currentTime = System.currentTimeMillis();
if (currentTime <= expire){ // accessToken
String claims = new String(Base64.decodeBase64(splitStr[1]),"UTF-8");
JSONObject claim = JSONObject.fromObject(claims);
userid = (String) claim.get("userid");
}
}
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(), e);
}
return userid;
}
/**
* jwt
*
* @param claims
* @param appSecretKey
* @return
*/
private String sign(JSONObject claims, String appSecretKey) {
String headerAndClaimsStr = getHeaderAndClaimsStr(claims);
String signed256 = signHmac256(headerAndClaimsStr, appSecretKey);
return headerAndClaimsStr + "." + signed256;
}
/**
*
*
* @param claims
* @return
*/
private String getHeaderAndClaimsStr(JSONObject claims) {
JSONObject header = new JSONObject();
header.put("alg", "HS256");
header.put("typ", "JWT");
header.put("exp", System.currentTimeMillis() + MAX_TOKEN_AGE * 1000L);
String headerStr = header.toString();
String claimsStr = claims.toString();
String headerAndClaimsStr = Base64.encodeBase64URLSafeString(headerStr.getBytes()) + "."
+ Base64.encodeBase64URLSafeString(claimsStr.getBytes());
return headerAndClaimsStr;
}
/**
* headerAndClaimsStr SHA1 sign
*
* @param headerAndClaimsStr
* @param appSecretKey
* @return
*/
private String signHmac256(String headerAndClaimsStr, String appSecretKey) {
SecretKey key = new SecretKeySpec(appSecretKey.getBytes(), "HmacSHA256");
String result = null;
try {
Mac mac;
mac = Mac.getInstance(key.getAlgorithm());
mac.init(key);
result = Base64.encodeBase64URLSafeString(mac.doFinal(headerAndClaimsStr.getBytes()));
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
log.error(e.getMessage(), e);
}
return result;
}
}
이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
콘텐츠 SaaS | JSON 스키마 양식 빌더Bloomreach Content를 위한 JSON Form Builder 맞춤형 통합을 개발합니다. 최근 Bloomreach Content SaaS는 내장 앱 프레임워크를 사용하여 혁신적인 콘텐츠 유형 필드를 구축할...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.