Token_使用JWT生成token
使用token替换session保存信息,防篡改
1.token三部分
header
{
"typ": "JWT",
"alg": "HS256"
}
payload
{
"iss": "ninghao.net",
"exp": "1438955445",
"name": "wanghao",
"admin": true
}
iss:Issuer,发行者
sub:Subject,主题
aud:Audience,观众
exp:Expiration time,过期时间
nbf:Not before
iat:Issued at,发行时间
jti:JWT ID
signature
先是用 Base64 编码的 header.payload ,再用加密算法加密一下,加密的时候要放进去一个 Secret ,这个相当于是一个密码,这个密码秘密地存储在服务端。
2.Base64 编码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
3.token生成 验证
生成token
1 import java.lang.reflect.Field; 2 import java.lang.reflect.Modifier; 3 import java.security.Key; 4 import java.util.Date; 5 import java.util.TreeMap; 6 import java.util.UUID; 7 8 import com.alibaba.fastjson.JSONObject; 9 10 import io.jsonwebtoken.JwtBuilder; 11 import io.jsonwebtoken.Jwts; 12 import io.jsonwebtoken.SignatureAlgorithm; 13 14 public class SignToken { 15 private String id; // token对外的ID号 16 17 private String mid; // 开发者编号 18 private String docId; // 合同编号 19 private String devId; // 签约的ID号码 20 21 private Date createTime; // Token的创建时间 22 private Date expiredIn; // Token的过期时间 23 24 private String value; // token的值 25 26 public SignToken(String mid, String docId, String devId) { 27 this.id=getUID(); 28 this.mid = mid; 29 this.docId = docId; 30 this.devId = devId; 31 } 32 33 34 public static synchronized String getUID() { 35 UUID uuid = UUID.randomUUID(); 36 return uuid.toString().replace("-", ""); 37 } 38 39 40 ///////////////////////////////////////////////////////// 41 public void setData(String jsonString) { 42 JSONObject json = JSONObject.parseObject(jsonString); 43 this.setData(json); 44 } 45 public String toJSONString() { 46 return this.toJSONObject().toJSONString(); 47 } 48 49 public void setData(JSONObject json) { 50 Class<?> clazz = this.getClass(); 51 for (String name: json.keySet()) { 52 Object value = json.get(name); 53 try { 54 Field field = clazz.getDeclaredField(name); 55 field.setAccessible(true); 56 field.set(this, value); 57 } catch (IllegalArgumentException e) { 58 e.printStackTrace(); 59 } catch (IllegalAccessException e) { 60 e.printStackTrace(); 61 } catch (NoSuchFieldException e) { 62 e.printStackTrace(); 63 } catch (SecurityException e) { 64 e.printStackTrace(); 65 } 66 } 67 } 68 69 public JSONObject toJSONObject() { 70 Field[] fields = this.getClass().getDeclaredFields(); 71 if (fields.length == 0) { 72 return null; 73 } 74 TreeMap<String, Object> map = new TreeMap<String, Object>(); 75 for (int i = 0; i < fields.length; i++) { 76 Field field = fields[i]; 77 int modifier = field.getModifiers(); 78 //if (!Modifier.isPublic(modifier) || Modifier.isStatic(modifier) || Modifier.isFinal(modifier)) { 79 // continue; 80 //} 81 if (Modifier.isStatic(modifier) || Modifier.isFinal(modifier)) { 82 continue; 83 } 84 field.setAccessible(true); 85 String name = field.getName(); 86 Object value = null; 87 try { 88 value = field.get(this); 89 } catch (IllegalArgumentException e) { 90 continue; 91 } catch (IllegalAccessException e) { 92 continue; 93 } 94 map.put(name, value); 95 } 96 JSONObject object = new JSONObject(map); 97 return object; 98 } 99 100 101 102 public String getId() { 103 return id; 104 } 105 106 public void setId(String id) { 107 this.id = id; 108 } 109 110 public String getMid() { 111 return mid; 112 } 113 114 public void setMid(String mid) { 115 this.mid = mid; 116 } 117 118 public String getDocId() { 119 return docId; 120 } 121 122 public void setDocId(String docId) { 123 this.docId = docId; 124 } 125 126 public String getDevId() { 127 return devId; 128 } 129 130 public void setDevId(String devId) { 131 this.devId = devId; 132 } 133 134 public Date getCreateTime() { 135 return createTime; 136 } 137 138 public void setCreateTime(Date createTime) { 139 this.createTime = createTime; 140 } 141 142 public Date getExpiredIn() { 143 return expiredIn; 144 } 145 146 public void setExpiredIn(Date expiredIn) { 147 this.expiredIn = expiredIn; 148 } 149 150 public String getValue() { 151 return value; 152 } 153 154 public void setValue(String value) { 155 this.value = value; 156 } 157 158 }
验签
1 package cn.bestsign.mixed.token; 2 3 import java.security.InvalidKeyException; 4 import java.security.Key; 5 import java.security.KeyFactory; 6 import java.security.KeyPair; 7 import java.security.KeyPairGenerator; 8 import java.security.NoSuchAlgorithmException; 9 import java.security.PrivateKey; 10 11 import java.security.Signature; 12 import java.security.SignatureException; 13 import java.security.interfaces.RSAPrivateKey; 14 import java.security.interfaces.RSAPublicKey; 15 import java.security.spec.InvalidKeySpecException; 16 import java.security.spec.PKCS8EncodedKeySpec; 17 import java.security.spec.X509EncodedKeySpec; 18 import java.util.Base64; 19 import java.util.Date; 20 import java.util.HashMap; 21 import java.util.Map; 22 23 import javax.xml.bind.DatatypeConverter; 24 25 import org.junit.Test; 26 27 import cn.gov.shnotary.fingerprint.service.PublicKey; 28 import io.jsonwebtoken.Jwt; 29 import io.jsonwebtoken.JwtBuilder; 30 import io.jsonwebtoken.Jwts; 31 import io.jsonwebtoken.SignatureAlgorithm; 32 import io.jsonwebtoken.impl.crypto.RsaProvider; 33 import net.sf.json.JSONObject; 34 35 public class SignTokenTest { 36 37 @Test 38 public void generateTokenTest3() throws Exception { 39 String pubKey="xxx"; 40 String priKey="xxx"; 41 byte[] privateKeyBytes = org.apache.commons.codec.binary.Base64.decodeBase64(priKey); 42 byte[] pubKeyBytes = org.apache.commons.codec.binary.Base64.decodeBase64(pubKey); 43 44 PrivateKey privateKey = getPrivateKey("RSA", privateKeyBytes); 45 java.security.PublicKey publicKey = getPublicKey("RSA", pubKeyBytes); 46 47 SignToken token1 = generateToken("E0000000000000000009", "101101-00000004", "13003618788", 7, SignatureAlgorithm.RS256, privateKey); 48 System.out.println(token1.getValue()); 49 String tokenString = token1.getValue(); 50 Jwt jwt = Jwts.parser().setSigningKey(publicKey).parse(tokenString); 51 System.out.println(jwt.getHeader()); 52 System.out.println(jwt.getBody()); 53 Jwt jwt = verifyToken(pubKey, token1.getValue()); 54 System.out.println(jwt.getHeader()); 55 System.out.println(jwt.getBody()); 56 JSONObject json = JSONObject.fromObject(jwt.getBody()); 57 JSONObject aud = json.getJSONObject("aud"); 58 System.out.println(aud); 59 } 60 61 public static PrivateKey getPrivateKey(String KEY_ALGORITHM, byte[] priKey) throws NoSuchAlgorithmException, InvalidKeySpecException { 62 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 63 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey); 64 return keyFactory.generatePrivate(pkcs8KeySpec); 65 } 66 67 public static java.security.PublicKey getPublicKey(String KEY_ALGORITHM, byte[] pubKey) throws InvalidKeySpecException, NoSuchAlgorithmException { 68 69 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey); 70 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 71 return keyFactory.generatePublic(x509KeySpec); 72 } 73 74 @Test 75 public void generateTokenTest2() throws Exception { 76 String pubKey=""; 77 String priKey=""; 78 79 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); 80 // 初始化密钥对儿生成器 81 keyPairGen.initialize(512); 82 // 生成密钥对儿 83 KeyPair keyPair = keyPairGen.generateKeyPair(); 84 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 85 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 86 87 SignToken token1 = generateToken("460cfedac66149c2a832e66fa1de28a6", "101101-00000004", "13003618788", 7, SignatureAlgorithm.RS256, privateKey); 88 System.out.println(token1.getValue()); 89 String tokenString = token1.getValue(); 90 Jwt jwt = Jwts.parser().setSigningKey(publicKey).parse(tokenString); 91 System.out.println(jwt.getHeader()); 92 System.out.println(jwt.getBody()); 93 } 94 95 96 97 @Test 98 public void generateTokenTest1() throws Exception { 99 KeyPair kp = RsaProvider.generateKeyPair(512); 100 java.security.PublicKey publicKey = kp.getPublic(); 101 PrivateKey privateKey = kp.getPrivate(); 102 103 SignToken token1 = generateToken("460cfedac66149c2a832e66fa1de28a6", "101101-00000004", "13003618788", 7, SignatureAlgorithm.RS256, privateKey); 104 System.out.println(token1.getValue()); 105 String tokenString = token1.getValue(); 106 107 // String tokenInfo[] = tokenString.split("\\."); 108 // for (String str : tokenInfo) { 109 // 110 // // String info = new String(Base64.getDecoder().decode(str)); 111 // // System.out.println(info); 112 // } 113 114 Jwt jwt = Jwts.parser().setSigningKey(publicKey).parse(tokenString); 115 System.out.println(jwt.getHeader()); 116 System.out.println(jwt.getBody()); 117 118 // Jwts.parser().setSigningKey(publicKey).parseClaimsJws(jwt).getBody(); 119 120 } 121 122 public SignToken generateToken(String mid, String docId, String devId, long delay, SignatureAlgorithm alg, Key signingKey) { 123 SignToken token = new SignToken(mid, docId, devId); 124 // 定义开始时间 125 Date now = new Date(); 126 Date end = new Date(now.getTime() + delay * 24 * 60 * 60 * 1000); 127 token.setCreateTime(now); 128 token.setExpiredIn(end); 129 130 // 构建一个Token 131 JwtBuilder builder = Jwts.builder().setId(token.getId()); 132 builder.setIssuedAt(token.getCreateTime()); // Token颁布的时间 133 builder.setExpiration(token.getExpiredIn()); // Token失效的时间 134 135 builder.setIssuer(mid); //发行者 授权者"ssqian.com.cn" 136 builder.setSubject("hand-sign"); //主题 137 builder.setAudience(token.toJSONString()); // 观众 138 builder.signWith(alg, signingKey); 139 140 token.setValue(builder.compact()); 141 return token; 142 143 } 144 145 public static byte[] rsaSign(byte[] data, String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { 146 // 解密由base64编码的私钥 147 byte[] privateKeyBytes = org.apache.commons.codec.binary.Base64.decodeBase64(privateKey); 148 149 // 构造PKCS8EncodedKeySpec对象 150 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes); 151 152 // KEY_ALGORITHM 指定的加密算法 153 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 154 155 // 取私钥匙对象 156 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); 157 158 // 用私钥对信息生成数字签名 159 Signature signature = Signature.getInstance("SHA1withRSA"); 160 signature.initSign(priKey); 161 signature.update(data); 162 163 return signature.sign(); 164 } 165 166 167 }