简介:JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准( RFC 7519 ),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。
-
简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快
-
自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库
原理性的东西可以参考 http://www.jianshu.com/p/576dbf44b2ae 这里只介绍在jeesite项目中怎么使用.
(1).首先引入jwt依赖jar包
<!--jjwt--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.7.0</version> </dependency>
(2).创建JwtUtil类,包括创建jwt方法和解析jwt方法
import com.weichai.common.mapper.JsonMapper; import com.weichai.modules.rest.config.Constant; import com.weichai.modules.rest.entity.AppUser; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.apache.commons.codec.binary.Base64; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Date; @Component public class JwtUtil { @Value("${spring.profiles.active}") private String profiles; /** * 由字符串生成加密key * @return */ public SecretKey generalKey(){ String stringKey = profiles+ Constant.JWT_SECRET; byte[] encodedKey = Base64.decodeBase64(stringKey); SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); return key; } /** * 创建jwt * @param id * @param subject * @param ttlMillis * @return * @throws Exception */ public String createJWT(String id, String subject, long ttlMillis) throws Exception { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); SecretKey key = generalKey(); JwtBuilder builder = Jwts.builder() .setId(id) .setIssuedAt(now) .setSubject(subject) .signWith(signatureAlgorithm, key); if (ttlMillis >= 0) { long expMillis = nowMillis + ttlMillis; Date exp = new Date(expMillis); builder.setExpiration(exp); } return builder.compact(); } /** * 解密jwt * @param jwt * @return * @throws Exception */ public Claims parseJWT(String jwt) throws Exception { SecretKey key = generalKey(); Claims claims = Jwts.parser() .setSigningKey(key) .parseClaimsJws(jwt).getBody(); return claims; } /** * 生成subject信息 * @param appUser * @return */ public static String generalSubject(AppUser appUser){ return JsonMapper.toJsonString(appUser); } }
(3)登录成功后将用户信息放入jwt中,生成后返回给app端
String subject = JwtUtil.generalSubject(appUser);--将用户信息转换成json格式 String token = jwt.createJWT(Constant.JWT_ID, subject, Constant.JWT_TTL); ret.put("userInfo",appUser); ret.put("userToken", token);
(4)app端登陆成功页面每次请求都会在header中带着jwt信息,请求数据(ionic2中请求方式)
public httpPostWithAuth(url: string, body: any) { let userToken = this.storageService.read<string>('userToken'); //alert(userToken); let headers = new Headers(); headers.append('Content-Type', 'application/json'); headers.append('Authorization', userToken); let options = new RequestOptions({ headers: headers }); return this.http.post(url, body, options).toPromise().then(res => res.json()) .catch(err => { this.handleError(err); }); }
(5)服务端获取header中jwt,进行解析,如果jwt过期则返回错误码提示用户重新登录;如果jwt解密正常,则可以获得用户信息,根据情况进行操作,最后再次刷新token,将最新token返回给app端。
String userToken = request.getHeader("Authorization"); if(userToken==null || "".equals(userToken)){ return new ApiReponseData.Builder("401").message("用户未授权").build(); } AppUser au = new AppUser(); try { //根据userToken 获取用户信息 Claims claims = jwt.parseJWT(userToken); au = (AppUser) JsonMapper.fromJsonString(claims.getSubject(), AppUser.class);--解密jwt得到用户信息 }catch(Exception e){ e.printStackTrace(); return new ApiReponseData.Builder("401").message("用户未授权").build(); }
String subject = JwtUtil.generalSubject(au);--获取最新用户信息生成最新jwt,传回app端 String token = jwt.createJWT(Constant.JWT_ID, subject, Constant.JWT_TTL); j.put("userToken",token);