SpringBoot中使用JWT的實(shí)戰(zhàn)
JWT 簡介
JWT(JSON Web Token)是一種用于身份驗(yàn)證和授權(quán)的開放標(biāo)準(zhǔn)(RFC 7519),它使用JSON格式傳輸信息,可以在不同系統(tǒng)之間安全地傳遞數(shù)據(jù)。JWT由三部分組成:頭部、載荷和簽名。頭部包含算法和類型信息,載荷包含用戶信息和其他元數(shù)據(jù),簽名用于驗(yàn)證JWT的真實(shí)性和完整性。JWT的優(yōu)點(diǎn)包括可擴(kuò)展性、跨平臺、無狀態(tài)和安全性高等。它被廣泛應(yīng)用于Web應(yīng)用程序、移動(dòng)應(yīng)用程序和API等領(lǐng)域。
JWT 身份認(rèn)證流程
- 客戶端向服務(wù)器發(fā)送用戶名和密碼,通常使用POST請求方式,將用戶名和密碼作為請求體發(fā)送給服務(wù)器。
- 服務(wù)器驗(yàn)證用戶名和密碼的正確性,如果驗(yàn)證通過,生成一個(gè)JWT令牌,并將令牌返回給客戶端。JWT令牌包括三部分:頭部、載荷和簽名。頭部包含令牌類型和加密算法,載荷包含用戶信息和過期時(shí)間等信息,簽名用于驗(yàn)證令牌的真實(shí)性。
- 客戶端將JWT令牌保存在本地,通常使用localStorage或sessionStorage等方式保存。
- 客戶端向服務(wù)器發(fā)送請求,請求頭部包含JWT令牌。通常使用Authorization頭部字段,格式為Bearer <token>,其中<token>為JWT令牌。
- 服務(wù)器驗(yàn)證JWT令牌的真實(shí)性,通常使用JWT庫進(jìn)行驗(yàn)證。驗(yàn)證過程包括以下步驟:解析JWT令牌,驗(yàn)證頭部和載荷的簽名是否正確,驗(yàn)證令牌是否過期,驗(yàn)證令牌是否被篡改等。如果驗(yàn)證通過,返回請求結(jié)果;否則返回錯(cuò)誤信息。
案例分享
下面是一個(gè)使用Spring Boot和JWT進(jìn)行身份認(rèn)證的示例:
1、后端代碼
1.1 添加依賴
在pom.xml文件中添加以下依賴:
? ? ? ? <dependency> ? ? ? ? ? ? <groupId>io.jsonwebtoken</groupId> ? ? ? ? ? ? <artifactId>jjwt</artifactId> ? ? ? ? ? ? <version>0.9.1</version> ? ? ? ? </dependency> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>javax.xml.bind</groupId> ? ? ? ? ? ? <artifactId>jaxb-api</artifactId> ? ? ? ? ? ? <version>2.3.1</version> ? ? ? ? </dependency> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>com.sun.xml.bind</groupId> ? ? ? ? ? ? <artifactId>jaxb-core</artifactId> ? ? ? ? ? ? <version>2.3.0.1</version> ? ? ? ? </dependency> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>com.sun.xml.bind</groupId> ? ? ? ? ? ? <artifactId>jaxb-impl</artifactId> ? ? ? ? ? ? <version>2.3.1</version> ? ? ? ? </dependency>
1.2 添加 ShiroConfig 配置類
添加一個(gè) ShiroConfig 類,用于配置Shiro框架的安全管理器和過濾器。
其中包含了三個(gè)方法:shiroFilterFactoryBean、defaultWebSecurityManager和realm。
- shiroFilterFactoryBean方法用于配置Shiro的過濾器,包括設(shè)置攔截規(guī)則、放行請求和設(shè)置默認(rèn)的登錄頁等。
- defaultWebSecurityManager方法用于配置Shiro的安全管理器,包括設(shè)置記住我功能和將自定義域?qū)ο蠼唤oSpring管理等。
- realm方法用于創(chuàng)建自定義域?qū)ο?,包括設(shè)置憑證匹配器、開啟緩存和將認(rèn)證和授權(quán)緩存寫入Redis等。
整個(gè)類的作用是為Shiro框架提供安全管理和過濾器的配置。
代碼如下:
package zk.gch.temperature.shiro; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.realm.Realm; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.CookieRememberMeManager; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.SimpleCookie; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import zk.gch.temperature.filter.JwtAuthenticationFilter; import java.util.LinkedHashMap; import javax.servlet.Filter; import java.util.HashMap; import java.util.Map; @Configuration public class ShiroConfig { ? ? // ?shiro中的過濾器 交給spring容器管理 ? ? @Bean ? ? public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ? ? ? ? System.out.println("securityManager = " + securityManager); ? ? ? ? ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); ? ? ? ? shiroFilterFactoryBean.setSecurityManager(securityManager); ? ? ? ? //配置攔截的規(guī)則 ? ? ? ? Map<String, Filter> filters = new HashMap<>(); ? ? ? ? filters.put("jwt", new JwtAuthenticationFilter()); ? ? ? ? shiroFilterFactoryBean.setFilters(filters); ? ? ? ? LinkedHashMap<String, String> map = new LinkedHashMap<>(); ? ? ? ? //放行登錄請求 ?anon ?可匿名訪問 ? ? ? ? map.put("/user/login", "anon"); ? ? ? ? map.put("/user/add", "anon"); ? ? ? ? map.put("/register.html", "anon"); ? ? ? ? // 放行靜態(tài)資源 ? ? ? ? map.put("/dist/**", "anon"); ? ? ? ? // 放行驗(yàn)證碼請求 ? ? ? ? map.put("/captcha/getCaptcha", "anon"); ? ? ? ? //已登錄或“記住我”的用戶才能訪問 ? ? ? ? map.put("/**", "user"); ? ? ? ? //放行所有攜帶token請求的訪問 ? ? ? ? map.put("/**", "jwt"); ? ? ? ? // 設(shè)置默認(rèn)的登錄頁 ? ? ? ? shiroFilterFactoryBean.setLoginUrl("/login.html"); ? ? ? ? shiroFilterFactoryBean.setFilterChainDefinitionMap(map); ? ? ? ? return shiroFilterFactoryBean; ? ? } ? ? // 將安全管理器交由spring管理 ? ? @Bean ? ? public DefaultWebSecurityManager defaultWebSecurityManager(Realm realm) { ? ? ? ? DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); ? ? ? ? // 設(shè)置一周免登錄 ? ? ? ? CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); ? ? ? ? SimpleCookie rmbme = new SimpleCookie("rmbme"); ? ? ? ? rmbme.setMaxAge(60*60*24*7); ? ? ? ? cookieRememberMeManager.setCookie(rmbme); ? ? ? ? defaultWebSecurityManager.setRememberMeManager(cookieRememberMeManager); ? ? ? ? defaultWebSecurityManager.setRealm(realm); ? ? ? ? return defaultWebSecurityManager; ? ? } ? ? // 將自定義域?qū)ο?交給spring管理 ? ? @Bean ? ? public Realm realm() { ? ? ? ? CustomerRealm customerRealm = new CustomerRealm(); ? ? ? ? //設(shè)置憑證匹配器 ?MD5 ? ? ? ? HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher("MD5"); ? ? ? ? hashedCredentialsMatcher.setHashIterations(20); ? ? ? ? customerRealm.setCredentialsMatcher(hashedCredentialsMatcher); ? ? ? ? // 開啟shiro的緩存 ?開啟全局緩存 ? ? ? ? customerRealm.setCachingEnabled(true); ? ? ? ? //將認(rèn)證和授權(quán)緩存寫入redis ? 分布式緩存 ? ? ? ? customerRealm.setCacheManager(new RedisCacheManager()); ? ? ? ? // 設(shè)置認(rèn)證緩存 ? ? ? ? customerRealm.setAuthenticationCachingEnabled(true); ? ? ? ? customerRealm.setAuthenticationCacheName("authentication"); ? ? ? ? // 設(shè)置授權(quán)緩存 ? ? ? ? customerRealm.setAuthorizationCachingEnabled(true); ? ? ? ? customerRealm.setAuthorizationCacheName("authorization"); ? ? ? ? return customerRealm; ? ? } }
1.3 添加 JwtUtil 工具類
JwtUtil 工具類是一個(gè)用于生成和解析JWT(JSON Web Token)的工具類。JWT是一種用于身份驗(yàn)證和授權(quán)的開放標(biāo)準(zhǔn),它可以在客戶端和服務(wù)器之間傳遞安全可靠的信息。
該工具類中包含了生成JWT的方法createJWT(),可以設(shè)置token中要存放的數(shù)據(jù)、過期時(shí)間等信息,并使用HS256對稱加密算法簽名。同時(shí),該工具類還包含了解析JWT的方法parseJWT(),可以解析出token中存放的數(shù)據(jù)。此外,該工具類還包含了一些常量和輔助方法,如JWT_TTL、JWT_KEY、getUUID()等。
代碼如下:
package zk.gch.temperature.utils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.stereotype.Component; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; import java.util.Date; import java.util.UUID; @Component public class JwtUtil { ? ? //有效期為 ? ? public static final Long JWT_TTL = 60 * 60 *1000L;// 60 * 60 *1000 ?一個(gè)小時(shí) ? ? //設(shè)置秘鑰明文 ? ? public static final String JWT_KEY = "sangeng"; ? ? public static String getUUID(){ ? ? ? ? String token = UUID.randomUUID().toString().replaceAll("-", ""); ? ? ? ? return token; ? ? } ? ? /** ? ? ?* 生成jtw ? ? ?* @param subject token中要存放的數(shù)據(jù)(json格式) ? ? ?* @return ? ? ?*/ ? ? public static String createJWT(String subject) { ? ? ? ? JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 設(shè)置過期時(shí)間 ? ? ? ? return builder.compact(); ? ? } ? ? /** ? ? ?* 生成jtw ? ? ?* @param subject token中要存放的數(shù)據(jù)(json格式) ? ? ?* @param ttlMillis token超時(shí)時(shí)間 ? ? ?* @return ? ? ?*/ ? ? public static String createJWT(String subject, Long ttlMillis) { ? ? ? ? JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 設(shè)置過期時(shí)間 ? ? ? ? return builder.compact(); ? ? } ? ? private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) { ? ? ? ? SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; ? ? ? ? SecretKey secretKey = generalKey(); ? ? ? ? long nowMillis = System.currentTimeMillis(); ? ? ? ? Date now = new Date(nowMillis); ? ? ? ? if(ttlMillis==null){ ? ? ? ? ? ? ttlMillis=JwtUtil.JWT_TTL; ? ? ? ? } ? ? ? ? long expMillis = nowMillis + ttlMillis; ? ? ? ? Date expDate = new Date(expMillis); ? ? ? ? return Jwts.builder() ? ? ? ? ? ? ? ? .setId(uuid) ? ? ? ? ? ? ?//唯一的ID ? ? ? ? ? ? ? ? .setSubject(subject) ? // 主題 ?可以是JSON數(shù)據(jù) ? ? ? ? ? ? ? ? .setIssuer("sg") ? ? // 簽發(fā)者 ? ? ? ? ? ? ? ? .setIssuedAt(now) ? ? ?// 簽發(fā)時(shí)間 ? ? ? ? ? ? ? ? .signWith(signatureAlgorithm, secretKey) //使用HS256對稱加密算法簽名, 第二個(gè)參數(shù)為秘鑰 ? ? ? ? ? ? ? ? .setExpiration(expDate); ? ? } ? ? /** ? ? ?* 創(chuàng)建token ? ? ?* @param id ? ? ?* @param subject ? ? ?* @param ttlMillis ? ? ?* @return ? ? ?*/ ? ? public static String createJWT(String id, String subject, Long ttlMillis) { ? ? ? ? JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 設(shè)置過期時(shí)間 ? ? ? ? return builder.compact(); ? ? } ? ? public static void main(String[] args) throws Exception { ? ? ? ? String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjYWM2ZDVhZi1mNjVlLTQ0MDAtYjcxMi0zYWEwOGIyOTIwYjQiLCJzdWIiOiJzZyIsImlzcyI6InNnIiwiaWF0IjoxNjM4MTA2NzEyLCJleHAiOjE2MzgxMTAzMTJ9.JVsSbkP94wuczb4QryQbAke3ysBDIL5ou8fWsbt_ebg"; ? ? ? ? Claims claims = parseJWT(token); ? ? ? ? System.out.println(claims); ? ? } ? ? /** ? ? ?* 生成加密后的秘鑰 secretKey ? ? ?* @return ? ? ?*/ ? ? public static SecretKey generalKey() { ? ? ? ? byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY); ? ? ? ? SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); ? ? ? ? return key; ? ? } ? ? /** ? ? ?* 解析 ? ? ?* ? ? ?* @param jwt ? ? ?* @return ? ? ?* @throws Exception ? ? ?*/ ? ? public static Claims parseJWT(String jwt) throws Exception { ? ? ? ? SecretKey secretKey = generalKey(); ? ? ? ? return Jwts.parser() ? ? ? ? ? ? ? ? .setSigningKey(secretKey) ? ? ? ? ? ? ? ? .parseClaimsJws(jwt) ? ? ? ? ? ? ? ? .getBody(); ? ? } }
1.4 添加 JwtAuthenticationFilter 過濾器類
JwtAuthenticationFilter 類是一個(gè)基于JWT(JSON Web Token)的身份驗(yàn)證過濾器,用于在每個(gè)請求中驗(yàn)證用戶的身份。它首先從請求頭中獲取Authorization字段,然后解析其中的token并驗(yàn)證其有效性。如果token有效,則將用戶信息存入SecurityContextHolder中,以便后續(xù)的身份驗(yàn)證。如果token無效,則返回401 Unauthorized。最后,它放行請求,使其繼續(xù)處理。
代碼如下:
package zk.gch.temperature.filter; import io.jsonwebtoken.Claims; import org.apache.shiro.web.servlet.OncePerRequestFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import zk.gch.temperature.utils.JwtUtil; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component public class JwtAuthenticationFilter extends OncePerRequestFilter { ? ? @Autowired ? ? private JwtUtil jwtUtil; ? ? @Override ? ? protected void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { ? ? ? ? HttpServletRequest httpRequest = (HttpServletRequest) request; ? ? ? ? HttpServletResponse httpResponse = (HttpServletResponse) response; ? ? ? ? // 獲取請求頭中的Authorization字段 ? ? ? ? String header = httpRequest.getHeader("Authorization"); ? ? ? ? if (header != null && header.startsWith("Bearer ")) { ? ? ? ? ? ? // 獲取token ? ? ? ? ? ? String token = header.substring(7); ? ? ? ? ? ? System.out.println("token = " + token); ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? // 解析token并驗(yàn)證其有效性 ? ? ? ? ? ? ? ? Claims claims = jwtUtil.parseJWT(token); ? ? ? ? ? ? ? ? if (claims != null) { ? ? ? ? ? ? ? ? ? ? // 將用戶信息存入SecurityContextHolder中 // ? ? ? ? ? ? ? ? ? ?UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(claims.getSubject(), null, null); // ? ? ? ? ? ? ? ? ? ?SecurityContextHolder.getContext().setAuthentication(authentication); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? ? ? // 驗(yàn)證失敗,返回401 Unauthorized ? ? ? ? ? ? ? ? httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); ? ? ? ? ? ? ? ? return; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? // 放行請求 ? ? ? ? filterChain.doFilter(request, response); ? ? } }
1.5 添加 UserController 控制器類
主要代碼如下:
將JwtUtil添加到spring容器管理:
@Autowired private JwtUtil jwtUtil;
請求成功后,將token作為返回值,返回給前端:
String token = jwtUtil.createJWT(user.getId().toString(), JSON.toJSONString(user), JwtUtil.JWT_TTL);
全部代碼如下:
package zk.gch.temperature.controller; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.*; import zk.gch.temperature.commons.CodeMsg; import zk.gch.temperature.commons.ResponseResult; import zk.gch.temperature.dto.OhterPageDTO; import zk.gch.temperature.dto.UserLoginDTO; import zk.gch.temperature.dto.UserPageDTO; import zk.gch.temperature.dto.UserRegisterDTO; import zk.gch.temperature.entity.BasicInfo; import zk.gch.temperature.entity.Device; import zk.gch.temperature.entity.User; import zk.gch.temperature.service.UserService; import zk.gch.temperature.utils.JwtUtil; import javax.servlet.http.HttpSession; import java.util.Arrays; import java.util.List; @RestController @Api(tags="主用戶模塊") @RequestMapping("user") public class UserController { ? ? @Autowired ? ? private UserService userService; ? ? @Autowired ? ? private RedisTemplate redisTemplate; ? ? @Autowired ? ? private JwtUtil jwtUtil; ? ? @ApiOperation("用戶注冊") ? ? @PostMapping("add") ? ? public ResponseResult add(@RequestBody UserRegisterDTO user){ ? ? ? ? return userService.saveUser(user); ? ? } ? ? @ApiOperation("用戶登錄") ? ? @GetMapping("login") ? ? public ResponseResult login(UserLoginDTO userLoginDTO, HttpSession session){ ? ? ? ? System.out.println("userLoginDTO.getSessionId() = " + userLoginDTO.getSessionId()); ? ? ? ? String sessionId=""; ? ? ? ? // 1.判定用戶的驗(yàn)證碼是否正確 ? ? ? ? if(userLoginDTO.getSessionId()!=null){ ? ? ? ? ? ? sessionId=userLoginDTO.getSessionId(); ? ? ? ? }else{ ? ? ? ? ? ? sessionId=session.getId(); ? ? ? ? } ? ? ? ? String code = (String) redisTemplate.opsForValue().get(sessionId); ? ? ? ? System.out.println("code = " + code); ? ? ? ? String captcha = userLoginDTO.getCaptcha(); ? ? ? ? System.out.println("captcha = " + captcha); ? ? ? ? if(code==null){ // ?驗(yàn)證碼失效 ? ? ? ? ? ? return ?new ResponseResult(CodeMsg.CAPTCHA_EXPIRE); ? ? ? ? }else{ ? ? ? ? ? ? if (code.equals(captcha)){ // 驗(yàn)證碼正確 ? ? ? ? ? ? ? ? Subject subject = SecurityUtils.getSubject(); ? ? ? ? ? ? ? ? UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userLoginDTO.getName(), userLoginDTO.getPassword()); ? ? ? ? ? ? ? ? // 判定用戶是否開啟 免登錄 ? ? ? ? ? ? ? ? String rememberMe = userLoginDTO.getRememberMe(); ? ? ? ? ? ? ? ? if("true".equals(rememberMe)){ ? ? ? ? ? ? ? ? ? ? usernamePasswordToken.setRememberMe(true); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? subject.login(usernamePasswordToken); ? ? ? ? ? ? ? ? QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); ? ? ? ? ? ? ? ? userQueryWrapper.eq("name",userLoginDTO.getName()); ? ? ? ? ? ? ? ? User user = userService.getOne(userQueryWrapper); ? ? ? ? ? ? ? ? if(!userLoginDTO.getRole().equals(user.getRole())){//角色錯(cuò)誤 ? ? ? ? ? ? ? ? ? ? return ?new ResponseResult(CodeMsg.ROLE_ERROR); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? String token = jwtUtil.createJWT(user.getId().toString(), JSON.toJSONString(user), JwtUtil.JWT_TTL); ? ? ? ? ? ? ? ? return ?new ResponseResult(CodeMsg.SUCCESS,null,token); ? ? ? ? ? ? }else { ?// 驗(yàn)證碼錯(cuò)誤 ? ? ? ? ? ? ? ? return ?new ResponseResult(CodeMsg.CAPTCHA_ERROR); ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? @ApiOperation("用戶退出") ? ? @GetMapping("logout") ? ? public ResponseResult ?logout(){ ? ? ? ? Subject subject = SecurityUtils.getSubject(); ? ? ? ? subject.logout(); ? ? ? ? return ?new ResponseResult(CodeMsg.SUCCESS); ? ? } ? ? @ApiOperation("查詢用戶信息列表") ? ? @GetMapping("all") ? ? public ResponseResult selectPage(UserPageDTO userPageDTO){ ? ? ? ? return userService.selectPage(userPageDTO); ? ? } ? ? @ApiOperation(value = "根據(jù)用戶名查詢單個(gè)用戶信息") ? ? @GetMapping("getByName") ? ? public ResponseResult getByName(String name){ ? ? ? ? LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda(); ? ? ? ? lambda.eq((name!=null&&!"".equals(name)),User::getName,name); ? ? ? ? User user = userService.getOne(lambda); ? ? ? ? return new ResponseResult(CodeMsg.SUCCESS,null,user); ? ? } ? ? @ApiOperation(value = "根據(jù)id查詢單個(gè)用戶信息") ? ? @GetMapping("getById") ? ? public ResponseResult getById(Integer id){ ? ? ? ? User user = userService.getById(id); ? ? ? ? return new ResponseResult(CodeMsg.SUCCESS,null,user); ? ? } ? ? @ApiOperation("更新用戶信息(綁定設(shè)備)") ? ? @PutMapping("update") ? ? public ResponseResult update(@RequestBody User user){ ? ? ? ? userService.updateById(user); ? ? ? ? return new ResponseResult(CodeMsg.SUCCESS); ? ? } ? ? @ApiOperation("刪除用戶") ? ? @DeleteMapping("delete") ? ? public ResponseResult ?delete(Integer[] ids){ ? ? ? ? List<Integer> integers = Arrays.asList(ids); ? ? ? ? userService.removeBatchByIds(integers); ? ? ? ? return new ResponseResult(CodeMsg.SUCCESS); ? ? } ? ? //密碼重置 ? ? @ApiOperation("密碼重置") ? ? @PostMapping("/updatePwd") ? ? public ResponseResult updatePwd(Integer id){ ? ? ? ? return userService.updatePwd(id); ? ? } }
2、前端代碼
登陸成功的代碼如下:
$.get("/user/login",data,function (res) { if(res.code==0){ layer.msg(res.msg,{icon:1},function () { localStorage.setItem("token",res.data); window.location = 'index.html'; }) }else{ layer.msg(res.msg) } },"JSON")
主要就是將token存儲在localStorage中;
其他頁面請求接口時(shí),在請求頭中添加Authorization字段;代碼如下:
var token = localStorage.getItem("token"); table.render({ elem: '#currentTableId', url: '/other/all?userName=' + localStorage.getItem("name"), toolbar: '#toolbarDemo', beforeSend: function(xhr) { // 在請求頭中添加Authorization字段 xhr.setRequestHeader("Authorization", "Bearer " + token); }, cols: [[ {type: "checkbox", width: 50}, {field: 'id', title: 'ID', width: 100, sort: true, hide: true}, {field: 'name', title: '用戶名', width: 100}, {field: 'age', title: '年齡(周歲)', width: 100}, {field: 'height', title: '身高(cm)', width: 100}, {field: 'weight', title: '體重(kg)', width: 100}, {field: 'maxTem', title: '體溫最大值(℃)', width: 130}, {field: 'minTem', title: '體溫最小值(℃)', width: 130}, {field: 'tel', title: '聯(lián)系方式', Width: 100}, {field: 'userName', title: '主用戶名', hide: true}, {field: 'deviceId', title: '設(shè)備編號', width: 100}, {field: 'deviceState', title: '設(shè)備狀態(tài)', templet: '#stateSwitch'}, {field: 'createTime', title: '創(chuàng)建時(shí)間'}, {field: 'updateTime', title: '修改時(shí)間'}, {fixed: 'right', title: '操作', width: 134, minWidth: 125, toolbar: '#barDemo'} ]], limits: [5, 10, 15, 20, 25, 50], limit: 5, page: true, skin: 'line' });
主要代碼:
獲取token:var token = localStorage.getItem("token");
在請求頭中添加Authorization字段:
beforeSend: function(xhr) { // 在請求頭中添加Authorization字段 xhr.setRequestHeader("Authorization", "Bearer " + token); },
到此這篇關(guān)于SpringBoot中使用JWT的實(shí)戰(zhàn)的文章就介紹到這了,更多相關(guān)SpringBoot使用JWT內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot+SpringSecurity+JWT實(shí)現(xiàn)系統(tǒng)認(rèn)證與授權(quán)示例
- SpringBoot+SpringSecurity+jwt實(shí)現(xiàn)驗(yàn)證
- SpringBoot+JWT實(shí)現(xiàn)注冊、登錄、狀態(tài)續(xù)簽流程分析
- SpringBoot集成JWT實(shí)現(xiàn)登陸驗(yàn)證的方法詳解
- vue+springboot+shiro+jwt實(shí)現(xiàn)登錄功能
- Springboot整合JwtHelper實(shí)現(xiàn)非對稱加密
- SpringBoot整合JWT的實(shí)現(xiàn)示例
- JWT整合Springboot的方法步驟
- 基于Springboot實(shí)現(xiàn)JWT認(rèn)證的示例代碼
- SpringBoot整合JWT Token的完整步驟
- SpringBoot整合JWT的入門指南
相關(guān)文章
Java基于Calendar類輸出指定年份和月份的日歷代碼實(shí)例
這篇文章主要介紹了Java 使用Calendar類輸出指定年份和月份的日歷,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02Java JDK動(dòng)態(tài)代理的基本原理詳細(xì)介紹
這篇文章主要介紹了Java JDK動(dòng)態(tài)代理的基本原理詳細(xì)介紹的相關(guān)資料,這里對動(dòng)態(tài)代理進(jìn)行了詳解并附簡單實(shí)例代碼,需要的朋友可以參考下2017-01-01通過自定制LogManager實(shí)現(xiàn)程序完全自定義的logger
本章主要闡述怎么完全定制化LogManager來實(shí)現(xiàn)應(yīng)用程序完全自定制的logger,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03java開發(fā)之讀寫txt文件操作的實(shí)現(xiàn)
本篇文章介紹了,java開發(fā)之讀寫txt文件操作的實(shí)現(xiàn)。需要的朋友參考下2013-05-05詳解Spring Data Jpa當(dāng)屬性為Null也更新的完美解決方案
這篇文章主要介紹了詳解Spring Data Jpa當(dāng)屬性為Null也更新的完美解決方案,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02Java將字節(jié)轉(zhuǎn)換為十六進(jìn)制代碼分享
我們知道,在java中,一個(gè)byte 就是一個(gè)字節(jié),也就是八個(gè)二進(jìn)制位;而4個(gè)二進(jìn)制位就可以表示一個(gè)十六進(jìn)制位,所以一個(gè)byte可以轉(zhuǎn)化為2個(gè)十六進(jìn)制位。下面我們就來詳細(xì)看下具體方法吧。2016-01-01