底层架构 自承式光缆 ssm 主从复制 二代征信 oracle compilation ip Backbonejs vue优势 jq去除空格 jq获取最后一个子元素 增删改查sql语句 mysql删除一列 mysql错误代码1064 jq入口函数 vue与html5 python抛出异常 python调用自定义函数 python学习网站 python中import用法 java数组反转 java查看版本 java自学教程 java8时间 java学习平台 java时间格式化 java成员变量 java目录 java常用数据结构 linux安装教程 linux命令详解词典 linux操作系统原理 msdev 视频字幕提取器 begininvoke 脚本大全 cf透视辅助 robotstudio 怎么设置迅雷为默认下载器
当前位置: 首页 > 学习教程  > 编程语言

JWT鉴权的实现

2020/12/28 18:48:33 文章标签:

1 JWT 工具类 1.1 引入依赖 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version> </dependency>1.2 创建 JwtUtil package util;import io.jsonwebtoken.Claims; impor…

1 JWT 工具类

1.1 引入依赖

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

1.2 创建 JwtUtil

package util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * Created by Administrator on 2018/4/11.
 */
@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();
    }

}

思路:

  1. JWT 工具类,无非两个内容:生成 JWT、解析 JWT。
  2. 生成 JWT 的方法,需要 id、主题 subject、发布此 JWT 的时间(保证 JWT 不重复)、签证(传入签名算法和盐 key);由于本实例做的是不同用户的鉴权问题,这里指定 admin 用户才有权限签发 token,于是我们自定义一个 claim ;并且还需要设置一个过期时间,它最好体现在配置文件中,于是我们多创建一个变量 ttl(time to live)。
  3. 由于我们需要的 JWT 是一个字符串,用 compact() 方法生成就行。
  4. 解析 JWT 的方法,先用 parser() 方法,然后传入盐和 JWT 字符串,最后 getBody()

1.3 properties.yml 配置文件

在配置文件中写入盐 key 和 过期时间 ttl。

jwt:
	config:
		key: helloWorld
		ttl: 360000

2 签发 token

2.1 注入 JwtUtil 到容器

@SpringBootApplication
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }

    @Bean
    public IdWorker idWorker() {
        return new IdWorker(1, 1);
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

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

2.2 生成 token

调用 JWT 工具类,传入 id、登录名、角色,然后存在一个 map 中返回给前端。

    @Autowired
    private JwtUtil jwtUtil;

    @PostMapping(value = "/login")
    public Result login(@RequestBody Admin admin) {
        Admin adminLogin = adminService.login(admin);
        if (adminLogin == null) {
            return new Result(StatusCode.ERROR, false, "登录失败");
        }
        // 使得前后端可以通话的操作,采用JWT来实现
        // 生成令牌
        String token = jwtUtil.createJWT(adminLogin.getId(), adminLogin.getLoginname(), "admin");
        Map<String , Object> map = new HashMap<>();
        map.put("token", token);
        map.put("role", "admin");
        return new Result(StatusCode.OK, true, "登录成功", map);
    }

2.3 结果

可以从前端看到我们生成的 token 了。
在这里插入图片描述

3 解析 token

需求:删除用户,必须拥有管理员权限,否则不能删除。
前后端约定:前端请求微服务时需要添加头信息 Authorization,内容为 Bearer+空格+token

3.1 判断请求头

修改 UserService 的 deleteUserById 方法 ,判断请求中的头信息,提取 token 并验证权限。

    @Autowired
    JwtUtil jwtUtil;

    @Autowired
    HttpServletRequest request;

    public void deleteUserById(String userId) {
        String header = request.getHeader("Authorization");
        if (header == null || "".equals(header)) {
            throw new RuntimeException("没有Authorization请求头");
        }
        if (!header.startsWith("Bearer")) {
            throw new RuntimeException("Authorization非标准格式");
        }
        String token = header.substring(7);
        try {
            Claims claims = jwtUtil.parseJWT(token);
            String roles = (String) claims.get("roles");
            if (null == roles || !roles.equals("admin")) {
                throw new RuntimeException("用户角色错误");
            }
        } catch (Exception e) {
            throw new RuntimeException("token错误");
        }

        userDao.deleteById(userId);
    }

3.2 测试

原本的数据库用的 user 表内容:
在这里插入图片描述

(1)没有加 header 的时候:
在这里插入图片描述
(2)Authorization 不是按照格式来的时候:
在这里插入图片描述
(3)token 格式错误的时候:
在这里插入图片描述
(4)填入正确 token 的时候:
在这里插入图片描述


本文链接: http://www.dtmao.cc/news_show_550119.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?