您好,登錄后才能下訂單哦!
本篇內(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)登陸注冊
<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>
有一個(gè)JWT庫,里面還有一個(gè)User表
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
import lombok.Data; @Data public class User { private String username; private String password; private int id; }
@Mapper public interface UserDao { User login(User user); }
public interface UserService { User login(User user);//登錄接口 }
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("登錄失敗"); } }
@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; } }
<?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>
/** * 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)目概覽
測試驗(yàn)證是否能夠連通數(shù)據(jù)庫
訪問:localhost:8989/user/login?username=ylc&password=123456
@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
訪問:http://localhost:8989/test/verity
但是我們這樣寫在實(shí)際項(xiàng)目中是不合理的,把token生成的代碼放在了Controller中,業(yè)務(wù)邏輯是不能放在Controller層中的。假如很多接口都需要token來進(jìn)行驗(yàn)證保護(hù),那每一個(gè)接口都需要添加這樣一段代碼,造成代碼冗余。
如果是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就放入攔截器的路徑
在http請求頭中放入token,會被攔截器攔截驗(yàn)證token的有效性
到此,相信大家對“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í)!
免責(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)容。