jwt的简单使用
简介
使用jwt对数据进行存储加密,分为java和golang版本。
java版本
-
maven配置
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency>
-
工具类 JWTUtil.java
import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import lombok.Getter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Date; public class JWTUtil { private final static String ISS = "dust"; private final static String SECRET = "secret"; // 过期时间是3600秒,既是1个小时 private final static long EXPIRATION = 3600; /** * 生成token * @param userId 用户id * @return token */ public static String createToken(long userId){ Algorithm algorithm = Algorithm.HMAC384(SECRET); String token = JWT.create() .withIssuer(ISS).withIssuedAt(new Date()).withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION * 1000)) .withClaim("USER_ID",userId) .sign(algorithm); return token; } /** * 解析token * @param token token * @return long */ public static long analyzeToken(String token){ DecodedJWT decode = JWT.decode(token); return decode.getClaim("USER_ID").asLong(); } /** * 校验token的合法性 * @param token token * @return boolean */ public static boolean verifyToken(String token){ Algorithm algorithm = Algorithm.HMAC384(SECRET); JWTVerifier verifier = JWT.require(algorithm) .withIssuer(ISS) .build(); //Reusable verifier instance try { // 验证不通过会出现异常 verifier.verify(token); } catch(Exception ex){ return false; } return true; } }
-
测试 JWTTests.java
import org.junit.Test; public class JWTTests { @Test public void createTokenTest(){ String token = JwtUtil.createToken(12345678); System.out.println(token); // eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpc3MiOiJkdXN0IiwiVVNFUl9JRCI6MTIzNDU2Nzh9.qUNgiHKB5uIWhhpf8GM6hdcaE9hTvDJG9UmmMpcCPpfncduQ713aKI7VMhCedJWP } @Test public void decodeTokenTest(){ String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpc3MiOiJkdXN0IiwiVVNFUl9JRCI6MTIzNDU2Nzh9.qUNgiHKB5uIWhhpf8GM6hdcaE9hTvDJG9UmmMpcCPpfncduQ713aKI7VMhCedJWP"; System.out.println(JwtUtil.analyzeToken(token)); // 12345678 } @Test public void verifyTokenTest(){ String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpc3MiOiJkdXN0IiwiVVNFUl9JRCI6MTIzNDU2Nzh9.qUNgiHKB5uIWhhpf8GM6hdcaE9hTvDJG9UmmMpcCPpfncduQ713aKI7VMhCedJWP"; System.out.println(JwtUtil.verifyToken(token)); // true } }
golang版本
-
导入包
go get -u github.com/dgrijalva/jwt-
-
JWTUtil.go
package testcase import ( "errors" "log" "time" "github.com/dgrijalva/jwt-go" ) type JWT struct { SigningKey []byte } var ( TokenExpired error = errors.New("Token is expired") TokenNotValidYet error = errors.New("Token not active yet") TokenMalformed error = errors.New("That's not even a token") TokenInvalid error = errors.New("Couldn't handle this token:") SignKey string = "dust" ) type CustomClaims struct { ID int64 `json:"id"` jwt.StandardClaims } func NewJWT() *JWT { return &JWT{ []byte(GetSignKey()), } } func GetSignKey() string { return SignKey } func SetSignKey(key string) string { SignKey = key return SignKey } func (j *JWT) CreateToken(claims CustomClaims) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(j.SigningKey) } func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) { token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { return j.SigningKey, nil }) if err != nil { if ve, ok := err.(*jwt.ValidationError); ok { if ve.Errors&jwt.ValidationErrorMalformed != 0 { return nil, TokenMalformed } else if ve.Errors&jwt.ValidationErrorExpired != 0 { // Token is expired return nil, TokenExpired } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 { return nil, TokenNotValidYet } else { return nil, TokenInvalid } } } if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { return claims, nil } return nil, TokenInvalid } func (j *JWT) RefreshToken(tokenString string) (string, error) { jwt.TimeFunc = func() time.Time { return time.Unix(0, 0) } token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { return j.SigningKey, nil }) if err != nil { return "", err } if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { jwt.TimeFunc = time.Now claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix() return j.CreateToken(*claims) } return "", TokenInvalid } // 生成令牌 func GenerateToken(id int64) (token string, err error) { j := NewJWT() claims := CustomClaims{ id, jwt.StandardClaims{ //NotBefore: int64(time.Now().Unix() - 1000), // 签名生效时间 ExpiresAt: int64(time.Now().Unix() + 1*60), // 过期时间 一小时 Issuer: "dust", //签名的发行者 }, } if token, err = j.CreateToken(claims); err != nil { log.Printf( "j.CreateToken(claims) err:%s", err.Error()) return } return token, nil }
-
测试JWTUtil_test.go
package testcase import ( "testing" "time" ) func TestGenerateToken(t *testing.T) { var ( token string err error ) if token, err = GenerateToken(123456); err != nil { t.Fatalf("GenerateToken错误,错误信息:%s", err.Error()) } t.Logf("token 值:%s", token) } func TestParseToken(t *testing.T) { var ( err error claims *CustomClaims ) token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MjM0NTY3LCJleHAiOjE1NjI4MTAyNTIsImlzcyI6ImR1c3QifQ.OxY2F0mOX8Y8XhMPHcgxmXENyHAwg_i9eCWqokIw0QE" jwt := NewJWT() if claims, err = jwt.ParseToken(token); err != nil { t.Fatalf("ParseToken错误,错误信息:%s", err.Error()) } t.Logf("claims中ID 值:%d", claims.ID) } func TestRefreshToken(t *testing.T) { var ( err error newToken string ) //token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTIzNDU2LCJleHAiOjE1NjI3NTA3NzcsImlzcyI6ImR1c3QiLCJuYmYiOjE1NjI3NDk3MTd9.W-qTms5UeuBRtF6VfksaZeZANZWfP5NdFHwYPGDMp98" jwt := NewJWT() createToken, _ := GenerateToken(234567) time.Sleep(62 * time.Second) if _, err = jwt.ParseToken(createToken); err != nil && err == TokenExpired { if newToken,err = jwt.RefreshToken(createToken); err == nil { t.Logf("newToken 值:%s", newToken) } else { t.Fatalf("RefreshToken错误,错误信息:%s", err.Error()) } } }