JTW——03,springboot整合JWT

一、封装工具类

public class JWTUtils {
    private static String SECRET = "token!Q@W#E$R";

    /**
     * 生产token
     */
    public static String getToken(Map<String, String> map) {
        JWTCreator.Builder builder = JWT.create();

        //payload
        map.forEach((k, v) -> {
            builder.withClaim(k, v);
        });

        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, 7); //默认7天过期

        builder.withExpiresAt(instance.getTime());//指定令牌的过期时间
        String token = builder.sign(Algorithm.HMAC256(SECRET));//签名
        return token;
    }

    /**
     * 验证token
     */
    public static DecodedJWT verify(String token) {
        //如果有任何验证异常,此处都会抛出异常
        DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
        return decodedJWT;
    }
    
}

二、搭建环境

1、数据库

就是一个表,三个字段

在这里插入图片描述创建一个springboot项目,省略了。。。。

2、导入依赖包

mysql,lombok,mybatis-plus,jwt

		<dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>

        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>

3、数据库配置文件

#数据库连接配置
spring.datasource.username=root
spring.datasource.password=123456
#mysql5~8 驱动不同driver-class-name     8需要增加时区的配置serverTimezone=UTC
#useSSL=false 安全连接
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus_study_one?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

4、封装JWT工具类

public class JWTUtils {
    private static String SECRET = "token!Q@W#E$R";

    /**
     * 生产token
     */
    public static String getToken(Map<String, String> map) {
        JWTCreator.Builder builder = JWT.create();

        //payload
        map.forEach((k, v) -> {
            builder.withClaim(k, v);
        });

        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, 7); //默认7天过期

        builder.withExpiresAt(instance.getTime());//指定令牌的过期时间
        String token = builder.sign(Algorithm.HMAC256(SECRET));//签名
        return token;
    }

    /**
     * 验证token
     */
    public static DecodedJWT verify(String token) {
        //如果有任何验证异常,此处都会抛出异常
        DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
        return decodedJWT;
    }

}

5、实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Admin {

    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
    private String password;
}

6、service

public interface AdminService extends IService<Admin> {
    /**
     * 登录接口
     *
     * @param admin 表单中的user
     * @return 数据库中查询到的User
     */
    Admin login(Admin admin);
}

7、servicelmpl

@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Override
    public Admin login(Admin admin) {
        QueryWrapper<Admin> wrapper = new QueryWrapper<>();
        wrapper.eq("name",admin.getName());
        wrapper.eq("password",admin.getPassword());
        System.out.println(admin.getName());
        System.out.println(admin.getPassword());
        //若出现多个结果使用list或map
        Admin adminDB = adminMapper.selectOne(wrapper); //查询一个数据,若出现多个结果使用list或map

        if (adminDB != null) {
            return adminDB;
        }
        throw new RuntimeException("认证失败");
    }

}

8、mapper

@Repository
public interface AdminMapper extends BaseMapper<Admin> {
}

完成的目录结构如下:

在这里插入图片描述

三、生成token

写一下controller

@RestController
public class AdminController {

    @Autowired
    private AdminService adminService;

    @GetMapping("/user/login")
    public Map<String, Object> login(Admin admin) {
        Map<String, Object> map = new HashMap<>();
        try {
            Admin adminDB = adminService.login(admin);

            Map<String, String> payload = new HashMap<>();
            payload.put("id", Integer.toString(adminDB.getId()));
            payload.put("name", adminDB.getName());
            String token = JWTUtils.getToken(payload);

            map.put("state", true);
            map.put("msg", "登录成功");
            map.put("token", token);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            map.put("state", false);
            map.put("msg", e.getMessage());
            map.put("token", "");
        }
        return map;
    }
}

使用postman,输入正确的账号密码,token创建成功

在这里插入图片描述
输入错误的账号密码,则失败

在这里插入图片描述

四、验证token

在admincontroller加上一个验证方法

	@PostMapping("/user/test")
    public Map<String, Object> test(String token) {
        Map<String,Object> map = new HashMap<>();
        System.out.println(token);
        try {
            DecodedJWT verify = JWTUtils.verify(token); //验证令牌
            map.put("state",true);
            map.put("msg","请求成功");
            return map;
        } catch (SignatureVerificationException e) {
            e.printStackTrace();
            map.put("msg","无效签名");
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            map.put("msg","token过期!");
        } catch (AlgorithmMismatchException e) {
            e.printStackTrace();
            map.put("msg","token算法不一致");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("msg","token无效");
        }
        map.put("state",false);
        return map;
    }

生成一个token后验证,成功

在这里插入图片描述
把token修改之后,验证,失败

在这里插入图片描述

五、拦截器

通过上面的代码可以发现,是不是以后每写一个接口,都要先写一堆的验证代码验证一下啊?就非常的冗余,不合理,所以要解决掉这个问题。使用拦截器。

5.1 定义拦截器

public class JWTInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {

        //获取请求头中的令牌
        String token = request.getHeader("token");
        System.out.println(token);

        Map<String, Object> map = new HashMap<>();
        try {
            JWTUtils.verify(token);
            return true;
        } catch (SignatureVerificationException e) {
            e.printStackTrace();
            map.put("msg", "签名不一致");
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            map.put("msg", "令牌过期");
        } catch (AlgorithmMismatchException e) {
            e.printStackTrace();
            map.put("msg", "算法不匹配");
        } catch (InvalidClaimException e) {
            e.printStackTrace();
            map.put("msg", "失效的payload");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("msg", "token无效");
        }

        map.put("state", false);

        //响应到前台: 将map转为json
        String json = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(json);
        return false;
    }
}

5.2 注册拦截器

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                .addPathPatterns("/user/test")  //这个是拦截的路径
                .excludePathPatterns("/user/login")     //这个是不拦截的路径
        ;
    }
}

5.3 获取JWT中的payload

修改一下admincontroller

 	@PostMapping("/user/test")
    public Map<String, Object> test(HttpServletRequest request) {
        String token = request.getHeader("token");
        DecodedJWT verify = JWTUtils.verify(token);
        String id = verify.getClaim("id").asString();
        String name = verify.getClaim("name").asString();
        System.out.println(id);
        System.out.println(name);

        // 业务逻辑
        Map<String, Object> map = new HashMap<>();
        map.put("state", true);
        map.put("msg", "请求成功");
        return map;
    }

添加修改完之后,整体是这样的

在这里插入图片描述
重启一下项目,验证一下效果

生成token之后,在头部加入token,OK没有问题

在这里插入图片描述

一键三连有没有捏~~

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值