概念:
JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。
优点是在分布式系统中,很好地解决了单点登录问题,很容易解决了session共享的问题。
缺点是无法作废已颁布的令牌/不易应对数据过期。
JWT 只是一种规范,具体应用,还是需要开发人员自己实现取数据的过程。
一般实现过程是这样的:
1.用户登陆后生成jwt token。
2.以后每次客户端访问在请求头或者cookie 中带上此cookie。
3.服务端接收此token后,获取用户信息,获取用户上下文数据,用户编写代码获取自己相关的数据。
JWT生成代码实现:
1.编辑POM.xml文件,加入下面的片段
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency>
2.JWT生成和解析过程。
package com.neo.util; import java.util.Base64; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.springframework.util.StringUtils; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; public class JwtUtil { /** * 加密的密码,这个密码不能对外面泄漏。 */ public static final String SECRET = "JKKLJOoasdlfj"; /** token 过期时间: 10天 */ public static final int calendarField = Calendar.DATE; public static final int calendarInterval = 10; /** * JWT生成Token.<br/> * * JWT构成: header, payload, signature * * @param user_id 用户ID * @param name 用户名称 * * 这些参数可以扩展的注意不要放入敏感信息,比如密码。 * */ public static String createToken(Long user_id,String name) throws Exception { Date iatDate = new Date(); // expire time Calendar nowTime = Calendar.getInstance(); nowTime.add(calendarField, calendarInterval); Date expiresDate = nowTime.getTime(); // header Map Map<String, Object> map = new HashMap<String, Object>(); map.put("alg", "HS256"); map.put("typ", "JWT"); // build token // param backups {iss:Service, aud:APP} String token = JWT.create().withHeader(map) // header .withClaim("iss", "Service") // payload .withClaim("aud", "APP") .withClaim("user_id", null == user_id ? null : user_id.toString()) .withClaim("name", name) .withIssuedAt(iatDate) // sign time .withExpiresAt(expiresDate) // expire time .sign(Algorithm.HMAC256(SECRET)); // signature return token; } /** * 解密Token * * @param token * @return * @throws Exception */ public static Map<String, Claim> verifyToken(String token) { DecodedJWT jwt = null; try { JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build(); jwt = verifier.verify(token); } catch (Exception e) { // e.printStackTrace(); // token 校验失败, 抛出Token验证非法异常 } return jwt.getClaims(); } /** * 根据Token获取user_id * * @param token * @return user_id */ public static Long getAppUID(String token) { Map<String, Claim> claims = verifyToken(token); Claim user_id_claim = claims.get("user_id"); if (null == user_id_claim || StringUtils.isEmpty(user_id_claim.asString())) { // token 校验失败, 抛出Token验证非法异常 } return Long.valueOf(user_id_claim.asString()); } public static void main(String[] args) throws Exception { String token=createToken(9999L,"ray"); System.out.println(token); Long uid=getAppUID(token); Map<String, Claim> claims = verifyToken(token); System.out.println(claims.get("name").asString()); //eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJBUFAiLCJ1c2VyX2lkIjoiOTk5OSIsImlzcyI6IlNlcnZpY2UiLCJuYW1lIjoiemhhbmd5ZyIsImV4cCI6MTU0MTk0NzA4MSwiaWF0IjoxNTQxMDgzMDgxfQ.fUc0PSjdvR5ihHUv8hk7eQeUlv5RkmrsCZxq6bUXYDc byte[] bytes= Base64.getUrlDecoder().decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"); System.out.println(new String(bytes)); bytes= Base64.getUrlDecoder().decode("eyJhdWQiOiJBUFAiLCJ1c2VyX2lkIjoiOTk5OSIsImlzcyI6IlNlcnZpY2UiLCJuYW1lIjoiemhhbmd5ZyIsImV4cCI6MTU0MTk0NzA4MSwiaWF0IjoxNTQxMDgzMDgxfQ"); System.out.println(new String(bytes)); } }
需要注意的是,我们可以在token放入用户ID,用户名称等信息,不要放入权限密码等信息,因为TOKEN 会在有效期内不发生变化,另外头部和payload信息是base64编码,是可以被解码的。