Springboot整合JWT


一、Springboot整合JWT

強烈建議小伙伴們閱讀 JWT 基礎概念https://www.cnblogs.com/code-duck/p/13479792.html
再進行Springboot整合

1.創建Springboot項目

2.配置pom信息

<!--?xml version="1.0" encoding="UTF-8"?-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelversion>4.0.0</modelversion>

    <parent>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-parent</artifactid>
        <version>2.3.1.RELEASE</version>
        <relativepath>
    </relativepath></parent>

    <groupid>com.duck.code</groupid>
    <artifactid>Springboot-JWT</artifactid>
    <version>1.0-SNAPSHOT</version>
    
    <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>

        <!--引入jwt-->
        <dependency>
            <groupid>com.auth0</groupid>
            <artifactid>java-jwt</artifactid>
            <version>3.4.0</version>
        </dependency>

        <dependency>
            <groupid>org.projectlombok</groupid>
            <artifactid>lombok</artifactid>
            <optional>true</optional>
        </dependency>

        <!--mybatis plus-->
        <dependency>
            <groupid>com.baomidou</groupid>
            <artifactid>mybatis-plus-boot-starter</artifactid>
            <version>3.3.2</version>
        </dependency>

        <!--代碼生成器-->
        <dependency>
            <groupid>com.baomidou</groupid>
            <artifactid>mybatis-plus-generator</artifactid>
            <version>3.3.2</version>
        </dependency>

        <!--逆向工程需要模板引擎-->
        <dependency>
            <groupid>org.freemarker</groupid>
            <artifactid>freemarker</artifactid>
            <version>2.3.30</version>
        </dependency>

        <!--mysql依賴-->
        <dependency>
            <groupid>mysql</groupid>
            <artifactid>mysql-connector-java</artifactid>
            <scope>runtime</scope>
        </dependency>

        <!--連接池-->
        <dependency>
            <groupid>com.alibaba</groupid>
            <artifactid>druid</artifactid>
            <version>1.1.20</version>
        </dependency>
    </dependencies>
</project>

3.配置application配置文件信息

server:
  port: 8081
spring:
  datasource:
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_jwt?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    type: com.alibaba.druid.pool.DruidDataSource

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tb_   # 表明前綴
  type-aliases-package: com.code.duck.entity  # 實體類所在包
  mapper-locations: classpath*:/mapper/**Mapper.xml   # xml文件所在位置

5.Springboot主啟動類配置

@SpringBootApplication
@MapperScan("com.duck.code.mapper")
public class JWTApplication {
    public static void main(String[] args) {
        SpringApplication.run(JWTApplication.class,args);
    }
}

4.Springboot整合MybatisPlus

​ 使用MybatisPlus代碼生成器,生成entity、controller、service,service.impl、mapper、xml文件

代碼生成器參考本人:Springboot整合MybatisPlus的文章 https://www.cnblogs.com/code-duck/p/13481550.html

6.封裝JWT工具類

JWTUtil工具類主要用於生成JWT令牌(token)、核實token信息、對token進行解密

JWT抽象類

JWT抽象類中的三個方法,對應於上述三個功能

public abstract class JWT {

    /**
     * Decode a given Json Web Token.
     *
     * @param token with jwt format as string.
     * @return a decoded JWT.
     */
    public static DecodedJWT decode(String token) throws JWTDecodeException {
        return new JWTDecoder(token);
    }

    /**
     * Returns a {@link JWTVerifier} builder with the algorithm to be used to validate token signature.
     *
     * @param algorithm that will be used to verify the token's signature.
     * @return {@link JWTVerifier} builder
     * @throws IllegalArgumentException if the provided algorithm is null.
     */
    public static Verification require(Algorithm algorithm) {
        return JWTVerifier.init(algorithm);
    }

    /**
     * Returns a Json Web Token builder used to create and sign tokens
     *
     * @return a token builder.
     */
    public static JWTCreator.Builder create() {
        return JWTCreator.init();
    }
}

JWTUtil工具類

public class JWTUtil {

    // 用於JWT進行簽名加密的秘鑰
    private static String SECRET = "code-duck-*%#@*!&";

    /**
     * @Param: 傳入需要設置的payload信息
     * @return: 返回token
     */
    public static String generateToken(Map<string, string=""> map) {
        JWTCreator.Builder builder = JWT.create();

        // 將map內的信息傳入JWT的payload中
        map.forEach((k, v) -> {
            builder.withClaim(k, v);
        });

        // 設置JWT令牌的過期時間為60
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND, 60);
        builder.withExpiresAt(instance.getTime());

        // 設置簽名並返回token
        return builder.sign(Algorithm.HMAC256(SECRET)).toString();
    }

    /**
     * @Param: 傳入token
     * @return:
     */
    public static void verify(String token) {
        JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
    }

    /**
     * @Param: 傳入token
     * @return: 解密的token信息
     */
    public static DecodedJWT getTokenInfo(String token) {
        return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
    }
}

7.UserController控制器中聲明登錄接口

@RestController
@Slf4j
public class UserController {

    @Resource
    private UserService userService;

    @PostMapping(value = "/user/login")
    public Map<string, string=""> userLogin(@RequestBody User user) {
        log.info(user.getUsername());
        log.info(user.getPassword());

        QueryWrapper<user> wrapper = new QueryWrapper<>();

        wrapper.eq("username", user.getUsername());
        wrapper.eq("password",user.getPassword());
        // 數據庫中查詢用戶信息
        User one = userService.getOne(wrapper);

        HashMap<string, string=""> result = new HashMap<>(); // 返回結果信息給前端

        if (one == null){
            result.put("code","401");
            result.put("msg","用戶名或密碼錯誤");
        }

        Map<string, string=""> map = new HashMap<>(); //用來存放payload信息

        map.put("id",one.getId().toString());
        map.put("username",one.getUsername());
        map.put("role",one.getRole());

        // 生成token令牌
        String token = JWTUtil.generateToken(map);

        // 返回前端token
        result.put("code","200");
        result.put("msg","登錄成功");
        result.put("token",token);
        return result;
    }
}

8.啟動Springboot

使用postman進行接口測試,查看是否返回了正確響應,並生成了token令牌

image-20200811205734830

二、為Springboot配置攔截器

  • 當用戶登錄成功時,服務端為該用戶生成了一個時長為60的token令牌,"token": "xxx.xxx.xx"的形式 以返回給前端系統
  • 當前端在每次請求時,我們選擇將token令牌放至放入HTTP Header中的Authorization位
  • 服務器對所有的請求進行攔截並校驗token(除登錄接口外)。如果token 信息不正確或過時,則向前端返回錯誤代碼,校驗正確則放行。

創建JWT攔截器

在此處進行token校驗,如果校驗成功則放行,否則返回異常信息給前端系統

public class JWTInterceptor implements HandlerInterceptor {

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

        Map<string, string=""> map = new HashMap<>();

        //獲取請求頭中的token令牌
        String token = request.getHeader("token");
        try {
            JWTUtil.verify(token);//驗證令牌
            return true;//放行請求
        } 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("code", "403");//設置狀態
        //將 map 轉為json  jackson
        String json = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(json);
        return false;
    }
}

配置WebMvcConfigurer攔截器

在此處配置過濾規則:即添加JWTInterceptor token校驗攔截器、攔截非登錄接口外的一切/user接口

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                .excludePathPatterns("/user/login") // 登錄接口不用於token驗證
                .addPathPatterns("/user/**"); // 其他非登錄接口都需要進行token驗證
    }
}

在控制器中添加測試接口

@GetMapping(value = "/user/test")
public Map<string,string> test(HttpServletRequest request){
    
    Map<string, string=""> map = new HashMap<>();
    //處理自己業務邏輯
    String token = request.getHeader("token");
    DecodedJWT claims = JWTUtil.getTokenInfo(token);
    log.info("用戶id: [{}]",claims.getClaim("id").asString());
    log.info("用戶name: [{}]",claims.getClaim("username").asString());
    log.info("用戶role: [{}]",claims.getClaim("role").asString());
    map.put("code","200");
    map.put("msg","請求成功!");
    return map;
}

啟動Springboot進行測試

  1. 訪問http://localhost:8081/user/login進行登錄測試,獲取服務器端返回的token信息
  2. 測試http://localhost:8081/user/test,在其請求頭配置token信息

image-20200811211951236</string,></string,string></string,></string,></string,></string,></string,>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM