curl https://api.openai.com/v1/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer $OPENAI_API_KEY" -d '{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "You are a poetic assistant, skilled in explaining complex programming concepts with creative flair."
},
{
"role": "user",
"content": "Compose a poem that explains the concept of recursion in programming."
}
]
}'
Authorization: Bearer $OPENAI_API_KEY
,其中$OPENAI_API_KEY便是用于用户认证的token。我理解:将json格式的数据转换为在Web中用于用户认证的token。
{
"alg": "HS256",
"typ": "JWT"
}
(1)alg属性表示签名的算法,默认是 HMAC SHA256(写成 HS256);
(2)typ属性表示这个令牌(token)的类型,JWT统一写为"JWT"。
(1) iss (issuer):签发人
(2)exp (expiration time):过期时间
(3)sub (subject):主题
(4)aud (audience):受众
(5)nbf (Not Before):生效时间
(6)iat (Issued At):签发时间
(7)jti (JWT ID):编号
除了官方字段,咱还可以在这个部分定义私有字段,如下所示:
{
"name": "Forrest",
"admin": true
}
注意:不要把秘密信息放在这个JSON对象中,因为通常这个JSON对象被转换为字符串后,默认是不加密的,这就会被别人解析回JSON对象,里面的信息就暴露了。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.3</version>
</dependency>
否则,会报错:
java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/util/JacksonFeature
at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:656)
at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:558)
…
public class JwtUtils {
private static final String secret = "IntelliJ IDEA";
// 7天有效期
public static final long EXPIRE_TIME = 1000 * 60 * 60 * 24 * 7;
/**
* 生成jwt
*/
public static String encode(Map<String, Object> headerMap, Map<String, Object> playloadMap) {
return Jwts.builder()
.setHeader(headerMap)
.setClaims(playloadMap)
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
/**
* 解析jwt
*/
public static Map<String, Object> decode(String jwt) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(jwt)
.getBody();
}
}
@Test
public void testEncode() {
Map<String, Object> headerMap = new HashMap<>();
headerMap.put("type", "JWT");
headerMap.put("alg", "HS256");
Map<String, Object> playloadMap = new HashMap<>();
playloadMap.put("username", "Forrest");
playloadMap.put("exp", System.currentTimeMillis() + JwtUtils.EXPIRE_TIME);
playloadMap.put("jti", UUID.randomUUID().toString());
for (Map.Entry<String, Object> entry : playloadMap.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
String jwt = JwtUtils.encode(headerMap, playloadMap);
System.out.println(jwt);
}
Key = exp, Value = 1706023265921
Key = jti, Value = c212fde2-abf4-4149-9c48-c55c1a029e79
Key = username, Value = Forrest
eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJleHAiOjE3MDYwMjMyNjU5MjEsImp0aSI6ImMyMTJmZGUyLWFiZjQtNDE0OS05YzQ4LWM1NWMxYTAyOWU3OSIsInVzZXJuYW1lIjoiRm9ycmVzdCJ9.t-rnO5CgC5DuNShsWIHxu_HKAgIU75tDQnlDcIBCmm0
@Test
public void testDecode() {
String jwt = "eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJleHAiOjE3MDYwMjI3MzM2MTUsImp0aSI6ImFkMTRiZDEyLWNlN2EtNDBjNi1iYTJkLWU0MDllMTY4ZjIwYyIsInVzZXJuYW1lIjoiRm9ycmVzdCJ9.NuNW5PckkwWpFRobreKjrU6pDdosHnc3J2KhwxFW4xU";
Map<String, Object> map = JwtUtils.decode(jwt);
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
}
Key = exp, Value = 1706023265921
Key = jti, Value = c212fde2-abf4-4149-9c48-c55c1a029e79
Key = username, Value = Forrest