SpringBoot整合JWT

JWT简介

  • JWT是用于微服务之间传递用户信息的一段加密字符串,该字符串是一个JSON格式,各个微服务可以根据该JSON字符串识别用户的身份信息,这个JSON字符串可以封装用户的身份信息
  • JWT的构成
    • 头部(Header)
      • 头部用于描述JWT的基本信息,指定了令牌类型和加密算法
    • 载荷(Payload)
      • 载荷是存放有效信息的地方
        • 标准注册中的声明
          • iss: jwt签发者
          • sub: 当前令牌的描述说明
          • aud: 接收jwt的一方
          • exp: jwt的过期时间,过期时间必须大于签发时间
          • nbf: 定义在什么时间之前,该jwt都是不能使用的
          • iat: jwt的签发时间
          • jti: jwt的唯一身份标识
        • 公共的声明
          • 公共的声明可以添加任何信息,一般添加用户的相关信息或其他业务的必要信息,不建议添加敏感信息,因为该部分在客户端可解密
        • 私有的声明
          • 私有声明是提供者和消费者所共同定义的声明,不建议存放敏感的信息
    • 签名
      • jwt的第三部分是一个签证信息,用于校验令牌是否被修改
      • 签名信息由以下三个部分组成
        • Header(Base64后的)
        • Payload(Base64后的)
        • Secret(秘钥)
        • 签名的组成
          • 头部信息Base64 + 载荷Base64 + Header中声明的加密方式进行加盐Secret组合加密,从而构成第三部分,也就是所谓的签名

SpringBoot整合jwt操作

1.创建数据库,建立user_info表,用于用户认证数据

-- 创建数据库
create DATABASE if not exists jwt_test;
-- 使用当前创建的数据库
use jwt_test;
-- 创建表
create table user_info (
	id int primary key auto_increment,
	age int,
	username varchar(20),
	password varchar(15),
	address varchar(255)
);
-- 插入数据
insert into user_info(age,username,password,address) values (18,'zhangsan','123456','SZ');

2.创建springboot工程,pom依赖如下

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
        <!-- jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.18.2</version>
        </dependency>

        <!-- mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>

    </dependencies>

3.创建application.yaml文件,添加mybatis配置信息

server:
  port: 8080
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/jwt_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 123456
#配置mybatis的mapper映射文件位置
mybatis:
  mapper-locations: classpath:mappers/*xml

4.创建启动类JwtApplication.java

@SpringBootApplication
@MapperScan(basePackages = "com.zhuang.dao")
public class JwtApplication {
    public static void main(String[] args) {
        SpringApplication.run(JwtApplication.class, args);
    }
}

5.创建数据库对应的实体类UserInfo.java

@Data
public class UserInfo {
    private Integer id;
    private Integer age;
    private String username;
    private String password;
    private String address;
}

6.创建UserInfoDao接口,提供登录认证和获取用户信息方法

public interface UserInfoDao {
    /**
     * 查询用户数据
     *
     * @param username 用户名
     * @param password 密码
     * @return
     */
    UserInfo findByUsernameAndPassword(String username, String password);

    /**
     * 根据ID获取用户数据
     *
     * @param id
     * @return
     */
    UserInfo findUserInfoById(Integer id);
}

7.在resources目录下创建mappers目录,并创建对应的UserInfoDao.xml文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:给哪个接口配置的映射,写接口的全限定类名-->
<mapper namespace="com.zhuang.dao.UserInfoDao">
    <!--
    select标签:表示要执行查询语句; 
    id:给接口里哪个方法配置的,写方法名;
    parameterType: 参数类型
    resultType:结果集封装类型
    -->
    <select id="findByUsernameAndPassword" parameterType="string" resultType="com.zhuang.pojo.UserInfo">
        select id, age, username, address from user_info where username = #{username} and password = #{password};
    </select>

    <select id="findUserInfoById" resultType="com.zhuang.pojo.UserInfo">
        select id, age, username, address from user_info where id = #{id};
    </select>
</mapper>

8.创建对应的service层

//service接口
public interface UserInfoService {
    /**
     * 查询用户数据
     *
     * @param username 用户名
     * @param password 密码
     * @return
     */
    UserInfo findByUsernameAndPassword(String username, String password);

    /**
     * 根据ID获取用户数据
     *
     * @param id
     * @return
     */
    UserInfo findUserInfoById(Integer id);
}


//service实现类
@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoDao userInfoDao;

    /**
     * 查询用户数据
     *
     * @param username 用户名
     * @param password 密码
     * @return
     */
    @Override
    public UserInfo findByUsernameAndPassword(String username, String password) {
        return userInfoDao.findByUsernameAndPassword(username, password);
    }

    /**
     * 根据ID获取用户数据
     *
     * @param id
     * @return
     */
    @Override
    public UserInfo findUserInfoById(Integer id) {
        return userInfoDao.findUserInfoById(id);
    }
}

9.创建对应的controller层

@RestController
public class UserInfoController {

    @Autowired
    private UserInfoService userInfoService;

    /**
     * 登录
     *
     * @param userInfo 请求体
     * @return
     */
    @PostMapping("/user/login")
    public Map<String, String> login(@RequestBody UserInfo userInfo) {
        UserInfo user = userInfoService.findByUsernameAndPassword(userInfo.getUsername(), userInfo.getPassword());
        Map<String, String> map = new HashMap<>();
        if (user != null) {
            Map<String, String> payload = new HashMap<>();
            payload.put("userId", user.getId() + "");
            payload.put("username", user.getUsername());
            String token = JwtUtil.generateToken(payload);
            map.put("status", "OK");
            map.put("token", token);
            return map;
        }
        map.put("status", "failed");
        return map;
    }

    /**
     * 根据ID获取用户数据
     *
     * @param id 用户id
     * @return
     */
    @GetMapping("/user/info/id/{id}")
    public UserInfo getUserInfoById(@PathVariable(value = "id") Integer id) {
        return userInfoService.findUserInfoById(id);
    }
}

10.创建JwtUtil.java

public class JwtUtil {

    private static final String SECRET = "CCMetric";

    /**
     * 生成token
     *
     * @param payload 载荷,需要在token中存放的数据
     * @return
     */
    public static String generateToken(Map<String, String> payload) {
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, 1);
        JWTCreator.Builder builder = JWT.create();
        //载荷,生成token中保存的信息
        payload.forEach(builder::withClaim);
        return builder.withAudience("admin") //签发对象
                .withIssuedAt(new Date()) //发行时间
                .withExpiresAt(instance.getTime()) //过期时间
                .sign(Algorithm.HMAC256(SECRET)); //加密算法+盐
    }

    /**
     * 校验token,有异常,即为校验失败
     *
     * @param token token数据
     * @return
     */
    public static DecodedJWT verify(String token) {
        return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
    }

    /**
     * 根据token获取载荷信息
     *
     * @param token token数据
     * @return
     */
    public static Map<String, Claim> getPayloadByToken(String token) {
        return verify(token).getClaims();
    }
}

11.创建拦截器JwtInterceptor

public class JwtInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");
        Map<String, Object> map = new HashMap<>();
        if (token != null) {
            try {
                JwtUtil.verify(token);
                return true;
            } catch (Exception e) {
                map.put("msg", "token无效");
            }
        } else {
            map.put("msg", "token为空");
        }
        map.put("status", false);
        //错误信息响应到前台
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().print(new Gson().toJson(map));
        response.setStatus(HttpStatus.FORBIDDEN.value());
        return false;
    }
}

12.将拦截器JwtInterceptor添加配置

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    /**
     * 添加自定义的拦截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JwtInterceptor())
                .addPathPatterns("/**") //拦截路径
                .excludePathPatterns("/user/login"); //登录接口排除
    }
}

13.接口测试

  登录测试,返回token

 获取用户信息,提供伪造token

获取用于信息,提供正确token

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
课程简介:历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值