Java安全验证之jwt(json web token)
http://blog.csdn.net/u012017645/article/details/53585872
jwt token安全验证流程:用户发起登录请求,服务端创建一个加密后的jwt信息,作为token返回值,在后续请求中jwt信息作为请求头,服务端正确解密后可获取到存储的用户信息,表示验证通过;解密失败说明token无效或者已过期。
jwt token的组成:header.poyload.sign
- header:头部,主要包括参数的类型—JWT,加密算法—-RS512,头部由json字符串用base64编码生成;
- poload:载荷,存放需要保存的一些用户信息,主要包括主题、签发者、接受者、到期时间等,载荷也由json字符串用base64编码生成,不能存放敏感数据;
- sign:签名,防止恶意篡改数据。
依赖:
<!-- 使用JWT在用户和服务器之间传递安全可靠的信息 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>
jwt加解密的工具类:
package cn.lsh.util;
import java.security.Key;
import java.util.Date;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.lsh.entity.User;
import cn.lsh.vo.security.Audience;
import cn.lsh.vo.security.LoginParamter;
public class JwtUtils {
private static final Logger LOGGER=LoggerFactory.getLogger(JwtUtils.class);
private JwtUtils(){
}
/*
* 验证jwt是否合法,即解密
*/
public static Claims parseJWT(String jsonWebToken,String base64Security){
try {
return Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
.parseClaimsJws(jsonWebToken)
.getBody();
} catch (Exception e) {
// TODO: handle exception
LOGGER.error("exception message is: {}", ExceptionUtils.getStackTrace(e));
return null;
}
}
/*
* 创建jwt,即加密
*/
public static String createJWT(LoginParamter loginParamter,User user,Audience audience){
long ttlmillis=audience.getExpiresSecond()*1000;
String base64Security=audience.getBase64Secret();
Date now=new Date(System.currentTimeMillis());
//生成签名密钥
byte[] apiKeySecretBytes=DatatypeConverter.parseBase64Binary(base64Security);
Key signingKey=new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
//添加构成JWT的参数
JwtBuilder builder=Jwts.builder().setHeaderParam("typ", "JWT")//typ表示token的类型
.claim("role", user.getRole())// 自定义属性
.claim("unique_name", loginParamter.getUserName())
.claim("userid", user.getName())
.setIssuer(audience.getName())// 签发者
.setAudience(audience.getClientId())//接受者
.signWith(SignatureAlgorithm.HS256, signingKey);// 签名算法以及密匙
//添加Token过期时间
if(ttlmillis>=0){
Date exp=new Date(System.currentTimeMillis()+ttlmillis);
builder.setExpiration(exp)// 过期时间
.setNotBefore(now);// 失效时间
}
//生成JWT
return builder.compact();
}
public static void main(String[] args) {
Claims c=parseJWT("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoi566h55CG5ZGYIiwidW5pcXVlX25hbWUiOiJsaXVzaGlodWEiLCJ1c2VyaWQiOiJsaXVzaGlodWEiLCJpc3MiOiJsaXVzaGlodWEiLCJhdWQiOiIwOThmNmJjZDQ2MjFkMzczY2FkZTRlODMyNjI3YjRmNiIsImV4cCI6MTUwMjM1OTQ1NSwibmJmIjoxNTAyMzUyMjU0fQ.OeDN4deNUlDiUmwROjxw5_xrurJt46b1RZ0K5yNKH88",
"MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=");
System.out.println(c);
}
}
audience包含token的一些信息:
package cn.lsh.vo.security;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
@Data
//绑定属性的配置信息到该bean中,配置信息前缀为audience
@ConfigurationProperties(prefix="audience")
@Component
@ApiModel(value="JWT")
public class Audience {
@ApiModelProperty(value="传入的客户端id,相当于微信的openID",required=true)
private String clientId;
@ApiModelProperty(value="64位公钥",required=true)
private String base64Secret;
@ApiModelProperty(value="令牌发行者姓名",required=true)
private String name;
@ApiModelProperty(value="令牌有效时间,单位为秒",required=true)
private int expiresSecond;
}
一、在用户登录是生成token,返回给客户端
String accessToken=JwtUtils.createJWT(loginParamter, user, audience);
二、在用户下次请求是验证token
private boolean isValidJwt(HttpServletRequest request){
LOGGER.info("{} request to {}",request.getMethod(),request.getRequestURL());
String authorization=request.getHeader("Authorization");
LOGGER.info("authorization is: {}",authorization);
//access_token的头信息,定义为bearer
String headString=authorization.substring(0, 6).toLowerCase();
//compareTo逐个比较两个字符串中相对字符的ascll值,所有字符都相同返回0,发现小于时返回正整数,大于时返回负整数,即ascll值的差值。
if(headString.compareTo(Constants.BEARER)==0){
authorization=authorization.substring(6, authorization.length());
if(JwtUtils.parseJWT(authorization, audience.getBase64Secret())!=null){
return true;
}
}
return false;
}
还没有评论,来说两句吧...