springboot怎麼整合JWT實現身分認證
一、什麼是JWT
JSON Web Token (JWT),它是目前最受歡迎的跨域身份驗證解決方案。現在的專案開發一般都是前端端分離,這就牽涉到跨域和權鑑問題。
二、JWT組成
由三個部分組成:頭部(Header)、載重(Payload)與簽名(signature)
##頭(Header) :
頭部資訊由兩個部分組成1、令牌的類型,即JWT;2、使用的簽章演算法,例如HMASSHA256或RSA;#
{ "alg": "HS256", "typ": "JWT" }
載荷(Payload):
payload用來承載要傳遞的數據,它的json結構實際上是對JWT要傳遞的數據的一組聲明,這些聲明被JWT標準稱為claims,它的一個「屬性值對」其實就是一個claim(要求), 每一個claim的都代表特定的意義和作用。 我們可以在claim放一些業務資訊。簽章(signature):
簽章是把header和payload對應的json結構進行base64url編碼之後得到的兩個串用'英文句點號' 拼接起來,然後根據header裡面alg指定的簽章演算法產生出來的。演算法不同,簽章結果不同。以alg: HS256為例來說明前面的簽章如何來得到。
<!--jwt--> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.3</version> </dependency>
package com.lsl.exam.utils; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.lsl.exam.entity.TabUser; import java.util.Date; import java.util.HashMap; import java.util.Map; public class JwtUtil { private static final long EXPIRE_TIME = 1000 * 60 * 60 *24; //设置私钥 private static final String TOKEN_SECRET = "aa082c-66rt89-29sr3t-y9t7b8"; /** * 创建携带自定义信息和声明的自定义私钥的jwt * @param user 用户信息表 * @return jwt串 */ public static String creatJwt(TabUser user){ //构建头部信息 Map<String,Object> header = new HashMap<>(); header.put("typ","JWT"); header.put("alg","HS256"); //根据私钥构建密钥信息 Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); //根据当前用户密码构建密钥信息 // Algorithm algorithm = Algorithm.HMAC256(user.getUserpwd()); //设置过期时间为当前时间一天后 Date nowDate = new Date(); Date expireDate = new Date(System.currentTimeMillis() + EXPIRE_TIME); String jwt = JWT.create().withHeader(header) .withClaim("account",user.getAccount())//业务信息:员工号 .withClaim("username",user.getUsername())//业务信息:员工姓名 .withClaim("rolename",user.getRoleName())//业务信息:角色 .withIssuer("SERVICE")//声明,签名是有谁生成 例如 服务器 .withNotBefore(new Date())//声明,定义在什么时间之前,该jwt都是不可用的 .withExpiresAt(expireDate)//声明, 签名过期的时间 .sign(algorithm);//根据algorithm生成签名 return jwt; } }
package com.lsl.exam.controller; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.lsl.exam.entity.TabUser; import com.lsl.exam.entity.backresult.ResultVO; import com.lsl.exam.service.ITabRoleService; import com.lsl.exam.service.IUserService; import com.lsl.exam.utils.Base64Util; import com.lsl.exam.utils.JwtUtil; import com.lsl.exam.utils.ResultVoUtil; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/exam") public class UserController { private static final Logger LOG = org.slf4j.LoggerFactory.getLogger("UserController"); @Autowired IUserService userService; @Autowired ITabRoleService roleService; @PostMapping(value = "login",produces = "application/json;charset=UTF-8") @ResponseBody public ResultVO<?> login(@RequestBody Map params){ Map reuslt = new HashMap(); String account = params.get("account") == null ? "" : params.get("account").toString(); String pwd = params.get("pwd") == null ? "" : params.get("pwd").toString(); if ("".equals(account) || "".equals(pwd)){ return ResultVoUtil.error(30000,"用户名或者密码不能为空!"); } //pwd解密 String decodePwd = Base64Util.decode(pwd); if ("".contains(decodePwd)){ return ResultVoUtil.error(30000,"密码错误!"); } TabUser user = userService.getOne(new QueryWrapper<TabUser>() .eq("account",account) .eq("userpwd",decodePwd)); if (null == user){ return ResultVoUtil.error(30000,"用户名或者密码错误"); } //获取当前用户拥有的角色 String userId = user.getId(); Map roleMap = new HashMap(); roleMap.put("userId",userId); List<Map> roleList = roleService.qryRoleInfoByUserId(roleMap); List<String> roleNames = new ArrayList<>(); for(Map role : roleList){ roleNames.add(role.get("role").toString()); } user.setRoleName(JSON.toJSONString(roleNames)); //生成带有业务信息的jwt串 String jwt = JwtUtil.creatJwt(user); //把jwt和当前用户信息返给前端 reuslt.put("jwt",jwt); reuslt.put("roleNames",roleNames); reuslt.put("username",user.getUsername()); reuslt.put("account",user.getAccount()); return ResultVoUtil.success(reuslt); } @PostMapping(value = "qryUser",produces = "application/json;charset=UTF-8") @ResponseBody public Object qryUser(HttpServletRequest request){ //这里header中的信息是filter中放进去的 String account = request.getHeader("account"); String username = request.getHeader("username"); String rolename = request.getHeader("rolename"); List<TabUser> list = userService.list(); return ResultVoUtil.success(list); } }
package com.lsl.exam.filter; import com.alibaba.fastjson.JSON; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import com.lsl.exam.entity.backresult.ResultVO; import com.lsl.exam.utils.ResultVoUtil; import org.apache.tomcat.util.http.MimeHeaders; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * jwt校验过滤器 */ @Component @WebFilter(filterName = "jwtFilter",urlPatterns = {"/*"}) public class AuthJwtFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; String url = httpServletRequest.getRequestURL().toString(); //配置不进行jwt校验的请求路径 List<String> urlList = new ArrayList<>(); urlList.add("/exam/login"); boolean flag = false; for (String strUrl : urlList){ if (url.contains(strUrl)){ flag = true; } } try { if (!flag){ String token = httpServletRequest.getHeader("token"); //校验token,jwt过期有jwt自行校验,如果超时了,会执行catch里代码 DecodedJWT decodeJwt = JWT.require(Algorithm.HMAC256("aa082c-66rt89-29sr3t-y9t7b8")).build().verify(token); //获取jwt中的业务信息 String account = decodeJwt.getClaim("account").asString(); String username = decodeJwt.getClaim("username").asString(); String rolename = decodeJwt.getClaim("rolename").asString(); Map<String, String> headerMap = new HashMap<>(); headerMap.put("account",account); headerMap.put("username",username); headerMap.put("rolename",rolename); //把业务信息添加到request的header addHeader(httpServletRequest,headerMap); // Class<?> superclass = servletRequest.getClass().getSuperclass().getSuperclass(); // Field requestField = superclass.getDeclaredField("request"); // requestField.setAccessible(true); // RequestFacade requestFacadeInstance = (RequestFacade) requestField.get(servletRequest); RequestFacade requestFacadeInstance = (RequestFacade)superclass3; // Field requestField1 = requestFacadeInstance.getClass().getDeclaredField("request"); // requestField1.setAccessible(true); // Object requestInstance = requestField1.get(requestFacadeInstance); // Field coyoteRequestField = requestInstance.getClass().getDeclaredField("coyoteRequest"); // coyoteRequestField.setAccessible(true); // // Object coyoRequestInstance = requestField1.get(requestInstance); // Field headersField = coyoRequestInstance.getClass().getDeclaredField("headers"); // headersField.setAccessible(true); // // MimeHeaders headers = (MimeHeaders) headersField.get(coyoRequestInstance); // headers.removeHeader("token"); // headers.addValue("account").setString(account); // headers.addValue("username").setString(username); // headers.addValue("roleid").setString(roleid); // } } catch (Exception e) { //jwt校验失败,返给前端的code=1,前端要重定向到登录页面 PrintWriter writer = null; servletResponse.setCharacterEncoding("UTF-8"); servletResponse.setContentType("text/html; charset=utf-8"); try { writer = servletResponse.getWriter(); ResultVO vo = ResultVoUtil.successLogout(); String msg = JSON.toJSONString(vo); writer.println(msg); } catch (IOException ex) { } finally { if (writer != null){ writer.close(); } return; } } filterChain.doFilter(servletRequest,servletResponse); } /** * 向request的header中放业务信息 * @param request * @param headerMap */ private void addHeader(HttpServletRequest request, Map<String, String> headerMap) { if (headerMap==null||headerMap.isEmpty()){ return; } Class<? extends HttpServletRequest> c=request.getClass(); //System.out.println(c.getName()); System.out.println("request实现类="+c.getName()); try{ Field requestField=c.getDeclaredField("request"); requestField.setAccessible(true); Object o=requestField.get(request); Field coyoteRequest=o.getClass().getDeclaredField("coyoteRequest"); coyoteRequest.setAccessible(true); Object o2=coyoteRequest.get(o); System.out.println("coyoteRequest实现类="+o2.getClass().getName()); Field headers=o2.getClass().getDeclaredField("headers"); headers.setAccessible(true); MimeHeaders mimeHeaders=(MimeHeaders) headers.get(o2); for (Map.Entry<String,String> entry:headerMap.entrySet()){ mimeHeaders.removeHeader(entry.getKey()); mimeHeaders.addValue(entry.getKey()).setString(entry.getValue()); } }catch (Exception e){ e.printStackTrace(); } } @Override public void destroy() { } }
以上是springboot怎麼整合JWT實現身分認證的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Jasypt介紹Jasypt是一個java庫,它允許開發員以最少的努力為他/她的專案添加基本的加密功能,並且不需要對加密工作原理有深入的了解用於單向和雙向加密的高安全性、基於標準的加密技術。加密密碼,文本,數字,二進位檔案...適合整合到基於Spring的應用程式中,開放API,用於任何JCE提供者...添加如下依賴:com.github.ulisesbocchiojasypt-spring-boot-starter2. 1.1Jasypt好處保護我們的系統安全,即使程式碼洩露,也可以保證資料來源的

一、Redis實現分散式鎖原理為什麼需要分散式鎖在聊分散式鎖之前,有必要先解釋一下,為什麼需要分散式鎖。與分散式鎖相對就的是單機鎖,我們在寫多執行緒程式時,避免同時操作一個共享變數產生資料問題,通常會使用一把鎖來互斥以保證共享變數的正確性,其使用範圍是在同一個進程中。如果換做是多個進程,需要同時操作一個共享資源,如何互斥?現在的業務應用通常是微服務架構,這也意味著一個應用會部署多個進程,多個進程如果需要修改MySQL中的同一行記錄,為了避免操作亂序導致髒數據,此時就需要引入分佈式鎖了。想要實現分

springboot讀取文件,打成jar包後訪問不到最新開發出現一種情況,springboot打成jar包後讀取不到文件,原因是打包之後,文件的虛擬路徑是無效的,只能通過流去讀取。文件在resources下publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

在Springboot+Mybatis-plus不使用SQL語句進行多表添加操作我所遇到的問題準備工作在測試環境下模擬思維分解一下:創建出一個帶有參數的BrandDTO對像模擬對後台傳遞參數我所遇到的問題我們都知道,在我們使用Mybatis-plus中進行多表操作是極其困難的,如果你不使用Mybatis-plus-join這一類的工具,你只能去配置對應的Mapper.xml文件,配置又臭又長的ResultMap,然後再寫對應的sql語句,這種方法雖然看上去很麻煩,但具有很高的靈活性,可以讓我們

1.自訂RedisTemplate1.1、RedisAPI預設序列化機制基於API的Redis快取實作是使用RedisTemplate範本進行資料快取操作的,這裡開啟RedisTemplate類,查看該類別的源碼資訊publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations,BeanClassLoaderAware{//聲明了value的各種序列化方式,初始值為空@NullableprivateRedisSe

隨著網路的發展,越來越多的網站和應用需要提供API介面來進行資料互動。在這種情況下,API身份驗證和加密成為了非常重要的問題。而JWT和JWE作為一種流行的身份驗證和加密機制,在PHP的應用也越來越廣泛。那麼,本文將介紹如何在PHP中使用JWT和JWE進行API身份驗證和加密。 JWT的基本概念JWT代表JSONWe

SpringBoot和SpringMVC都是Java開發中常用的框架,但它們之間有一些明顯的差異。本文將探究這兩個框架的特點和用途,並對它們的差異進行比較。首先,我們來了解一下SpringBoot。 SpringBoot是由Pivotal團隊開發的,它旨在簡化基於Spring框架的應用程式的建立和部署。它提供了一種快速、輕量級的方式來建立獨立的、可執行

JWT(JSONWebToken)是一種輕量級的認證和授權機制,它使用JSON物件作為安全令牌,可以在多個系統之間安全地傳輸使用者身分資訊。而ThinkPHP6是一種基於PHP語言的高效、靈活的MVC框架,它提供了許多有用的工具和功能,其中就包括JWT認證機制。在本文中,我們將介紹如何使用ThinkPHP6進行JWT認證,以確保Web應用程式的安全性與可靠
