基于JWT的Token认证机制实现(二)

1,158 阅读3分钟

本片文章链接上一篇文章: www.jianshu.com/p/5e1a07f5c…

juejin.cn/post/684490…

Java的JJWT实现JWT.

JJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache License,版本2.0),JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性。

下面就来测试一下代码和步骤:

token的创建

(1)创建maven工程,引入依赖

<dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt</artifactId>
      <version>0.6.0</version>
</dependency>

(2)创建类CreateJwtTest,用于生成token

public class CreateJwtTest {
    public static void main(String[] args) {
        JwtBuilder builder= Jwts.builder().setId("888")
        .setSubject("小白")
        .setIssuedAt(new Date())
      .signWith(SignatureAlgorithm.HS256,"itcast");
      System.out.println( builder.compact() );
    }
}

setIssuedAt用于设置签发时间 signWith用于设置签名秘钥

(3)测试运行,输出如下: eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1MjM0M TM0NTh9.gq0J‐cOM_qCNqU_s‐d_IrRytaNenesPmqAIhQpYXHZk

token的解析

我们刚才已经创建了token ,在web应用中这个操作是由服务端进行然后发给客户端,客户端在下次向服务端发送请求时需要携带这个token(这就好像是拿着一张门票一样),那服务端接到这个token 应该解析出token中的信息(例如用户id),根据这些信息查询数据库返回相应的结果。创建ParseJwtTest:

public class ParseJwtTest {
      public static void main(String[] args) {
          String token="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiO
jE1MjM0MTM0NTh9.gq0J‐cOM_qCNqU_s‐d_IrRytaNenesPmqAIhQpYXHZk";

        Claims claims =Jwts.parser().setSigningKey("itcast").parseClaimsJws(token).getBody();
        System.out.println("id:"+claims.getId());
        System.out.println("subject:"+claims.getSubject());
        System.out.println("IssuedAt:"+claims.getIssuedAt());
      }
}

试着将token或签名秘钥篡改一下,会发现运行时就会报错,所以解析token也就是验证token

setExpiration 方法用于设置过期时间 测试运行,当未过期时可以正常读取,当过期时会引发 io.jsonwebtoken.ExpiredJwtException异常。

自定义claims

我们刚才的例子只是存储了id和subject两个信息,如果你想存储更多的信息(例如角色)可以定义自定义claims 创建CreateJwtTest3

public class CreateJwtTest3 {
public static void main(String[] args) {
//为了方便测试,我们将过期时间设置为1分钟
long now = System.currentTimeMillis();//当前时间
long exp = now + 1000*60;//过期时间为1分钟
JwtBuilder builder= Jwts.builder().setId("888")
.setSubject("小白")
.setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS256,"itcast")
.setExpiration(new Date(exp))
.claim("roles","admin")
.claim("logo","logo.png");
System.out.println( builder.compact() );
}
}

当我们使用SpringBoot 来实现时,一般把JWT验证放在常用子系统的模块的工具类中,

@ConfigurationProperties("jwt.config")
public class JwtUtil {
private String key ;
private long ttl ;//一个小时
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public long getTtl() {
return ttl;
}
public void setTtl(long ttl) {
this.ttl = ttl;
}
/**
* 生成JWT
*
* @param id
* @param subject
* @return
*/
public String createJWT(String id, String subject, String roles) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder builder = Jwts.builder().setId(id)
.setSubject(subject)
.setIssuedAt(now)
.signWith(SignatureAlgorithm.HS256, key).claim("roles",
roles);
if (ttl > 0) {
builder.setExpiration( new Date( nowMillis + ttl));
}
return builder.compact();
}
/**
* 解析JWT
* @param jwtStr
* @return
*/
public Claims parseJWT(String jwtStr){
return Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwtStr)
.getBody();
}
}

修改需要使用到该工具类的工程的application.yml, 添加配置

image.png

管理员登陆后台签发token

@Bean
public JwtUtil jwtUtil(){
return new util.JwtUtil();
}

下面讲把我登录的例子实例下:

@Autowired
private JwtUtil jwtUtil;
/**
* 用户登陆
* @param loginname
* @param password
* @return
*/
@RequestMapping(value="/login",method=RequestMethod.POST)
public Result login(@RequestBody Map<String,String> loginMap){
Admin admin =
adminService.findByLoginnameAndPassword(loginMap.get("loginname"),
loginMap.get("password"));
if(admin!=null){
//生成token
String token = jwtUtil.createJWT(admin.getId(),
admin.getLoginname(), "admin");
Map map=new HashMap();
map.put("token",token);
map.put("name",admin.getLoginname());//登陆名
return new Result(true,StatusCode.OK,"登陆成功",map);
}else{
return new Result(false,StatusCode.LOGINERROR,"用户名或密码错
误");
}
}

喜欢请点个赞

思想的碰撞最能促进技术的进步哦