一、JWT出现的背景
jwt令牌出现的背景,比如我们通过一个路由访问网站的时候,有些游客在知道url的情况下会跳过用户登录直接访问其他网页,这样不仅在逻辑上说不通(我没登陆咋就能使用其他功能?)还会造成信息泄露和访问不安全。这时候jwt令牌的出现就填充了这一空白。

具体地,在用户登陆之后生成一个JWT令牌,然后将该令牌下发给客户端,客户端将该令牌存储起来,在之后的每一次请求都将令牌带到服务端,服务端接受该请求之后对这个请求进行统一拦截,获取到令牌并验证真伪,如果令牌无效,直接拦截,如果有效则放行。
二、实战
首先项目目录如下,项目所需文件红框圈出:

2.1 pom.xml: 将JWT的依赖包引入pom文件中:
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>有需要自取:pom.xml一些必不可少的配置-CSDN博客
2.2 JwtUtils:工具类,用于jwt令牌的创建和解码
package com.bytedance.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;
public class JwtUtils {
    private static String signKey = "itheima";
    private static Long expire = 43200000L; // 24小时候过期
    /**
     * 生成JWT令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    public static String generateJwt(Map<String, Object> claims){
        String jwt = Jwts.builder()
                .addClaims(claims)
                .signWith(SignatureAlgorithm.HS256, signKey)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .compact();
        return jwt;
    }
    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}
2.3 LoginController.java : 创建登陆界面的接口,由前端提交员工信息(这里是一个Emp对象其实只需要username和password参数),当调empService这个bean对象的方法时传入,empService又调用empMapper的bean对象去数据库里检索是否有这个username和password,有的话则生成令牌并将生成的令牌作为返回信息返回即可,否则返回错误提示。
package com.bytedance.controller; // 改成自己包名
import com.bytedance.pojo.Emp;
import com.bytedance.pojo.Result;
import com.bytedance.service.EmpService;
import com.bytedance.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
public class LoginController {
    @Autowired
    private EmpService empService;
    @PostMapping("/login")
    public Result login(@RequestBody Emp emp){
        log.info("员工登陆的信息:{}",emp);
        Emp e = empService.login(emp);
        // 如果登陆成功,生成令牌,下发令牌
        if (e != null){
            Map<String,Object> claims = new HashMap<>();
            claims.put("id",e.getId());
            claims.put("name",e.getName());
            claims.put("username",e.getUsername());
            String jwtcode = JwtUtils.generateJwt(claims);
            return Result.success(jwtcode);
        }
        // 登陆失败,返回错误信息
        else{
            return Result.error("用户名或密码失败~");
        }
    }
}
2.4 EmpService.java : 这是一个接口,定义了login方法给实现类去实现。
package com.bytedance.service;
import com.bytedance.pojo.Emp;
import com.bytedance.pojo.PageBean;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.util.List;
public interface EmpService {
    Emp login(Emp emp);
}
2.5 EmpServicelmpl.java : EmpService的实现类,实现了login函数。这个login方法将接收到的emp对象传入empMapper类中的getByUsernameAndPassword方法,该方法去数据库中查询是否有一致的username和password。
package com.bytedance.service.impl;
import com.bytedance.mapper.EmpMapper;
import com.bytedance.pojo.Emp;
import com.bytedance.pojo.PageBean;
import com.bytedance.service.EmpService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class EmpServicelmpl implements EmpService {
    @Autowired
    private EmpMapper empMapper;
    @Override
    public Emp login(Emp emp) {
        return empMapper.getByUsernameAndPassword(emp);
    }
}
2.6 EmpMapper.java : 里面的getByUsernameAndPassword方法负责查询是否存在登陆的信息并返回结果。
package com.bytedance.mapper;
import com.bytedance.pojo.Emp;
import org.apache.ibatis.annotations.*;
import java.time.LocalDate;
import java.util.List;
@Mapper
public interface EmpMapper {
     @Select("select * from emp where username = #{username} and password = #{password}")
     Emp getByUsernameAndPassword(Emp emp);
}
三、验证

这样在前端页面就不能跳过登陆访问其他功能啦~







![[项目设计] 从零实现的高并发内存池(四)](https://img-blog.csdnimg.cn/c446ebae288e480d84f5d14d494c88bb.gif)











