溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證

發(fā)布時(shí)間:2022-01-04 13:50:24 來源:億速云 閱讀:186 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證”吧!

    JWT可以理解為一個(gè)加密的字符串,里面由三部分組成:頭部(Header)、負(fù)載(Payload)、簽名(signature)

    由base64加密后的header和payload使用.連接組成的字符串,然后通過header中聲明的加密方式進(jìn)行加鹽secret組合加密,然后就構(gòu)成了JWT字符串

    往期介紹了JWT相關(guān)概念以及基本操作,接下來介紹如何在SpringBoot中整合JWT實(shí)現(xiàn)登陸注冊

    SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證

    環(huán)境搭建

    1、新建一個(gè)SpringBoot項(xiàng)目Jwt-Demo,引入項(xiàng)目后面需要用到的jar包

      <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.1.3</version>
            </dependency>
            <!--引入mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.25</version>
            </dependency>
            <!--引入druid數(shù)據(jù)庫連接池-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.2.1</version>
            </dependency>
            <!--引入lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.12</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter-test</artifactId>
                <version>2.1.3</version>
            </dependency>
            <!--引入jwt-->
            <dependency>
                <groupId>com.auth0</groupId>
                <artifactId>java-jwt</artifactId>
                <version>3.4.0</version>
            </dependency>
        </dependencies>

    2、數(shù)據(jù)庫結(jié)構(gòu)

    SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證

    有一個(gè)JWT庫,里面還有一個(gè)User表

    3、配置文件application.properties

    server.port=8989
    
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/JWT?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
    spring.datasource.username=root
    spring.datasource.password=12345678
    
    #mybatis掃描的包
    mybatis.type-aliases-package=com.ylc
    #mapper文件路徑
    mybatis.mapper-locations=classpath:/**/*.xml
    
    #開啟sql打印日志  logging.level后面是mybatis對應(yīng)的方法接口所在的包
    logging.level.com.ylc.jwtdemo.dao=debug

    4、Entity包下新建一個(gè)User類

    import lombok.Data;
    
    @Data
    public class User {
        private  String username;
        private  String password;
        private  int id;
    }

    5、Dao包下新建一個(gè)UserDao

    @Mapper
    public interface UserDao {
    
        User login(User user);
    }

    6、Service包下新建一個(gè)USerService

    public interface UserService {
        User login(User user);//登錄接口
    }

    7、UseService的實(shí)現(xiàn)類UserServiceImp

    import java.util.HashMap;
    import java.util.Map;
    
    @Service
    public class UserServiceImpI implements UserService {
    
        @Autowired
        private UserDao userDao;
    
        @Override
        public User login(User user) {
            User userdb=userDao.login(user);
            if(userdb!=null)
            {
                Map<String,String> map=new HashMap<>();
                map.put("name",userdb.getUsername());
                return userdb;
            }
            throw  new RuntimeException("登錄失敗");
        }
    }

    8、controller包下新建一個(gè)UserController

    @RestController
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @GetMapping("/user/login")
        public Map<String,Object> login(User user)
        {
            log.info("用戶名:"+user.getUsername());
            log.info("密碼:"+user.getPassword());
            Map<String,Object> map=new HashMap<>();
            try {
                userService.login(user);
                map.put("msg","登錄成功");
                map.put("code","200");
            }
            catch (Exception ex)
            {
                map.put("msg","登錄失敗");
            }
    
            return map;
        }
    }

    9、在resource文件夾下新建一個(gè)Usermapper文件

    <?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.ylc.jwtdemo.dao.UserDao">
        <select id="login" parameterType="com.ylc.jwtdemo.entity.User" resultType="com.ylc.jwtdemo.entity.User">
            select *from user where username=#{username} and password=#{password}
        </select>
    </mapper>

    10、JWT工具類JwtUtils

    /**
     * JWT工具類
     * @author yanglingcong
     * @date 2021/12/31 11:24 AM
     */
    public class JwtUtils {
        //鑒權(quán) 相當(dāng)于私鑰保存在服務(wù)器上
        private  static  final String  secret="##@$%@#S#WS";
    
    
        /**
         * 生成token
         * @author yanglingcong
         * @date 2021/12/31 11:23 AM
         * @param map
         * @return String
         */
        public static  String getToken(Map<String,String> map)
        {
            Calendar instance=Calendar.getInstance();
            //默認(rèn)七天過期
            instance.add(Calendar.DATE,7);
            //創(chuàng)建JWT
            JWTCreator.Builder builder = JWT.create();
    
            //payload
            map.forEach((k,v)->{
                builder.withClaim(k,v);
            });
            //指定令牌過期時(shí)間
            builder.withExpiresAt(instance.getTime());
    
            String token=builder.sign(Algorithm.HMAC256(secret));
            return token;
        }
    
        /**
         * 驗(yàn)證token
         * @author yanglingcong
         * @date 2021/12/31 11:26 AM
         * @param token
         */
        public  static  DecodedJWT  verify(String token) {
            return  JWT.require(Algorithm.HMAC256(secret)).build().verify(token);
        }
    
    }

    整個(gè)項(xiàng)目概覽

    SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證

    測試驗(yàn)證是否能夠連通數(shù)據(jù)庫

    訪問:localhost:8989/user/login?username=ylc&password=123456

    SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證

    引入JWT

    @Slf4j
    @RestController
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @GetMapping("/user/login")
        public Map<String,Object> login(User user)
        {
            log.info("用戶名:"+user.getUsername());
            log.info("密碼:"+user.getPassword());
            Map<String,Object> map=new HashMap<>();
            try {
                userService.login(user);
                map.put("msg","登錄成功");
                map.put("code","200");
    
                Map<String,String> payload=new HashMap<>();
                payload.put("name",user.getUsername());
                String token= JwtUtils.getToken(payload);
                map.put("token",token);
            }
            catch (Exception ex)
            {
                map.put("msg","登錄失敗");
            }
    
            return map;
        }
    
        @PostMapping("/test/verity")
        public  Map<String,String> verityToken(String token)
        {
            Map<String, String> map=new HashMap<>();
            log.info("token為"+token);
            try {
                DecodedJWT verify = JwtUtils.verify(token);
                map.put("msg","驗(yàn)證成功");
                map.put("state","true");
            }
            catch (Exception exception)
            {
                map.put("msg","驗(yàn)證失敗");
                exception.printStackTrace();
            }
            return map;
        }
    }

    登錄操作

    訪問:http://localhost:8989/user/login?username=ylc&password=123456

    SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證

    驗(yàn)證操作

    訪問:http://localhost:8989/test/verity

    SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證

    但是我們這樣寫在實(shí)際項(xiàng)目中是不合理的,把token生成的代碼放在了Controller中,業(yè)務(wù)邏輯是不能放在Controller層中的。假如很多接口都需要token來進(jìn)行驗(yàn)證保護(hù),那每一個(gè)接口都需要添加這樣一段代碼,造成代碼冗余。

    程序優(yōu)化

    如果是web項(xiàng)目使用攔截器進(jìn)行優(yōu)化,如果是springcloud項(xiàng)目在網(wǎng)關(guān)層進(jìn)行攔截,下面演示如何使用攔截器攔截

    最好還把JWT生成token放在http請求頭,這樣就不需要把token當(dāng)成參數(shù)傳遞了

    新建一個(gè)攔截器JwtInterceptor

    /**
     * JWT攔截器
     * @author yanglingcong
     * @date 2021/12/31 12:39 PM
     */
    public class JwtInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            HashMap<String, String> map=new HashMap<>();
            //從http請求頭獲取token
            String token = request.getHeader("token");
            try {
                //如果驗(yàn)證成功放行請求
                DecodedJWT verify = JwtUtils.verify(token);
                return true;
            }
            catch (Exception exception)
            {
                map.put("msg","驗(yàn)證失?。?quot;+exception);
            }
            String json = new ObjectMapper().writeValueAsString(map);
            response.setContentType("application/json:charset=UTF=8");
            response.getWriter().println(json);
            return false;
        }
    }

    然后把攔截器注冊到過濾器中,新建一個(gè)過濾器InterceptConfig

    /**
     * @author yanglingcong
     */
    @Configuration
    public class InterceptConfig implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //添加攔截器
            registry.addInterceptor(new JwtInterceptor())
                    //攔截的路徑 需要進(jìn)行token驗(yàn)證的路徑
                    .addPathPatterns("/test/verity")
                    //放行的路徑
                    .excludePathPatterns("/user/login");
        }
    }

    登錄是不需要攔截的,其他請求如果有需要驗(yàn)證token就放入攔截器的路徑

    測試驗(yàn)證

    在http請求頭中放入token,會被攔截器攔截驗(yàn)證token的有效性

    SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證

    到此,相信大家對“SpringBoot集成JWT怎么實(shí)現(xiàn)token驗(yàn)證”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI