APP用户登录解决方案——JWT(json web token)生成Token

什么是JSON Web Token?

JSON Web Token(JWT)是一个开放式标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSON对象安全传输信息。这些信息可以通过数字签名进行验证和信任。可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对对JWT进行签名。

为什么使用JWT?

随着技术的发展,分布式web应用的普及,通过session管理用户登录状态成本越来越高,因此慢慢发展成为token的方式做登录身份校验,然后通过token去取redis中的缓存的用户信息,随着之后jwt的出现,校验方式更加简单便捷化,无需通过redis缓存,而是直接根据token取出保存的用户信息,以及对token可用性校验,单点登录更为简单。

JWT的优点:

 

  • 体积小,因而传输速度更快
  • 多样化的传输方式,可以通过URL传输、POST传输、请求头Header传输(常用)
  • 简单方便,服务端拿到jwt后无需再次查询数据库校验token可用性,也无需进行redis缓存校验
  • 在分布式系统中,很好地解决了单点登录问题
  • 很方便的解决了跨域授权问题,因为跨域无法共享cookie

JWT的缺点:

 

  • 因为JWT是无状态的,因此服务端无法控制已经生成的Token失效,是不可控的,这一点对于是否使用jwt是需要重点考量的
  • 获取到jwt也就拥有了登录权限,因此jwt是不可泄露的,网站最好使用https,防止中间攻击偷取jwt
  • 在退出登录 / 修改密码时怎样实现JWT Token失效https://segmentfault.com/q/1010000010043871

对于JWT安全性:

JWT被确实存在被窃取的问题,但是如果能得到别人的token,其实也就相当于能窃取别人的密码,这其实已经不是JWT安全性的问题。网络是存在多种不安全性的,对于传统的session登录的方式,如果别人能窃取登录后的sessionID,也就能模拟登录状态,这和JWT是类似的。为了安全,https加密非常有必要,对于JWT有效时间最好设置短一点。

使用JWT部分后端代码:

maven依赖:


    com.auth0
    java-jwt
    3.3.0

Java代码:

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.alibaba.druid.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;

/**
 * APP登录Token的生成和解析
 * 
 */
public class JwtToken {

	/** token秘钥,请勿泄露,请勿随便修改 backups:JKKLJOoasdlfj */
	public static final String SECRET = "JKKLJOoasdlfj";
	/** token 过期时间: 10天 */
	public static final int calendarField = Calendar.DATE;
	public static final int calendarInterval = 10;

	/**
	 * JWT生成Token.
* * JWT构成: header, payload, signature * * @param user_id * 登录成功后用户user_id, 参数user_id不可传空 */ public static String createToken(Long user_id) throws Exception { Date iatDate = new Date(); // expire time Calendar nowTime = Calendar.getInstance(); nowTime.add(calendarField, calendarInterval); Date expiresDate = nowTime.getTime(); // header Map Map map = new HashMap<>(); 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()) .withIssuedAt(iatDate) // sign time .withExpiresAt(expiresDate) // expire time .sign(Algorithm.HMAC256(SECRET)); // signature return token; } /** * 解密Token * * @param token * @return * @throws Exception */ public static Map 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 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()); } }

我的GitHub地址,欢迎Follow。
 

你可能感兴趣的:(APP用户登录解决方案——JWT(json web token)生成Token)