springboot+vue前后端分離項目中使用jwt實現(xiàn)登錄認證
一、后端代碼
1.響應(yīng)工具類
package com.etime.util; import com.etime.vo.ResponseModel; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.http.MediaType; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @Date 2024/6/10 10:00 * @Author liukang **/ public class ResponseUtil { public static void write(ResponseModel rm, HttpServletResponse response) throws IOException { // 構(gòu)造響應(yīng)頭 response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("utf-8"); // 解決跨域問題 設(shè)置跨域頭 response.setHeader("Access-Control-Allow-Origin","*"); // 輸出流 PrintWriter out = response.getWriter(); // 輸出 out.write(new ObjectMapper().writeValueAsString(rm)); // 關(guān)閉流 out.close(); } }
2.jwt工具類
package com.etime.util; import io.jsonwebtoken.*; import java.util.Date; import java.util.Map; import java.util.UUID; /** * @Date 2024/6/10 10:04 * @Author liukang **/ public class JwtUtil { private static String secret = "secret"; /** * 創(chuàng)建jwt * @author liukang * @date 10:36 2024/6/10 * @param expire * @param map * @return java.lang.String **/ public static String generateToken(long expire, Map map){ // 床jwt構(gòu)造器 JwtBuilder jwtBuilder = Jwts.builder(); // 生成jwt字符串 String jwt = jwtBuilder //頭部 .setHeaderParam("typ","JWT") .setHeaderParam("alg","HS256") // 載荷 .setClaims(map) // 設(shè)置多個自定義數(shù)據(jù) 位置只能放在前面,如果放在后面,那前面的載荷會失效 .setId(UUID.randomUUID().toString())// 唯一標識 .setIssuer("liukang")// 簽發(fā)人 .setIssuedAt(new Date())// 簽發(fā)時間 .setSubject("jwtDemo")// 主題 .setExpiration(new Date(System.currentTimeMillis()+expire))//過期時間 // 簽名 .signWith(SignatureAlgorithm.HS256,secret) .compact(); return jwt; } /** * 創(chuàng)建jwt * @author liukang * @date 10:36 2024/6/10 * @param expire * @return java.lang.String **/ public static String generateToken(long expire){ // 床jwt構(gòu)造器 JwtBuilder jwtBuilder = Jwts.builder(); // 生成jwt字符串 String jwt = jwtBuilder //頭部 .setHeaderParam("typ","JWT") .setHeaderParam("alg","HS256") // 載荷 .setId(UUID.randomUUID().toString())// 唯一標識 .setIssuer("liukang")// 簽發(fā)人 .setIssuedAt(new Date())// 簽發(fā)時間 .setSubject("jwtDemo")// 主題 .setExpiration(new Date(System.currentTimeMillis()+expire))//過期時間 // 簽名 .signWith(SignatureAlgorithm.HS256,secret) .compact(); return jwt; } /** * 解析jwt * @author liukang * @date 10:36 2024/6/10 * @param jwt * @return io.jsonwebtoken.Claims **/ public static Claims parseToken(String jwt){ Jws<Claims> claimsJws = Jwts.parser().setSigningKey(secret).parseClaimsJws(jwt); Claims playload = claimsJws.getBody(); return playload; } }
3.登錄用戶實體類
package com.etime.entity; import lombok.Data; /** * @Date 2024/6/10 10:39 * @Author liukang **/ @Data public class User { private String username; private String password; }
4.登錄接口
package com.etime.controller; import com.etime.entity.User; import com.etime.util.JwtUtil; import com.etime.vo.ResponseModel; import org.springframework.web.bind.annotation.*; /** * @Date 2024/6/10 10:38 * @Author liukang **/ @RestController @CrossOrigin public class LoginController { @PostMapping("/login") public ResponseModel login(@RequestBody User user){ Integer code = 200; String msg = "success"; String token = null; if(user.getUsername().equals("admin")&&user.getPassword().equals("123")){ // 生成jwt token = JwtUtil.generateToken(1000*10);// 設(shè)置有效期為10s }else { code = 500; msg = "failure"; } return new ResponseModel(code,msg,token); } }
5.測試接口
package com.etime.controller; import com.etime.vo.ResponseModel; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; /** * @Date 2024/6/10 12:51 * @Author liukang **/ @CrossOrigin @RestController public class TestController { @PostMapping("/test") public ResponseModel test() { return new ResponseModel(200,"success","測試請求接口成功!"); } }
6.過濾器
package com.etime.filter; import com.etime.util.JwtUtil; import com.etime.util.ResponseUtil; import com.etime.vo.ResponseModel; import com.sun.deploy.net.HttpResponse; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; import org.springframework.util.StringUtils; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @Description jwt過濾器 * @Date 2024/6/10 9:46 * @Author liukang **/ @WebFilter(urlPatterns = "/*") // 過濾所有路徑 public class JwtFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 得到兩個對象 HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; //直接放行 if(HttpMethod.OPTIONS.toString().equals(request.getMethod())){ filterChain.doFilter(request,response); return; } String requestURI = request.getRequestURI(); // 不含主機和端口號 if(requestURI.contains("/login")){ filterChain.doFilter(request,response); return; } // 得到請求頭的信息(accessToken) String token = request.getHeader("accessToken"); if(!StringUtils.hasText(token)){ //響應(yīng)前端錯誤的消息提示 ResponseModel responseModel = new ResponseModel(500,"failure","令牌缺失!"); ResponseUtil.write(responseModel,response); return; } // 解析Token信息 try { JwtUtil.parseToken(token); }catch (Exception e){ //響應(yīng)前端錯誤的消息提示 ResponseModel responseModel = new ResponseModel(401,"failure","令牌過期!"); ResponseUtil.write(responseModel,response); return; } filterChain.doFilter(request,response); } }
7.啟動類
package com.etime; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; /** * @Author liukang * @Date 2022/7/4 11:32 */ @SpringBootApplication @ServletComponentScan(basePackages = "com.etime.filter")// 這個包下激活WebFilter這個注解 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class); } }
二、前端代碼
登錄頁
<template> <div class="hello"> <form> 用戶名:<input v-model="username"/> <br> 密碼<input v-model="password" /> <br> <button @click="login">登錄</button> </form> </div> </template> <script> export default { data () { return { username:'', password:'', } }, methods:{ login(){ this.axios.post('http://localhost:8088/login',{ username:this.username, password:this.password, }).then(response => { console.log(response.data); if(response.data.code==200){ sessionStorage.setItem("accessToken",response.data.token) this.$router.push({ path: 'index'}); } }).catch(error => { console.error(error); }); } }, } </script> <style scoped> </style>
index 頁面
<template> <div> <button @click="test">請求受保護的接口</button> </div> </template> <script> export default { data () { return { } }, methods:{ test(){ const accessToken = sessionStorage.getItem('accessToken') let token = null if(accessToken){ token = accessToken } console.log(token) this.axios.post('http://localhost:8088/test',{},{headers:{accessToken:token} }).then(response => { // if(response.data.code==200){ console.log(response.data); // } }).catch(error => { console.error(error); }); }, }, } </script> <style scoped> </style>
三、效果展示
1.點擊登錄后,后端給前端辦法jwt令牌,前端將其存入sessionStorage中
2.點擊【請求后端受保護的接口】按鈕
3.繼續(xù)多次點擊【請求后端受保護的接口】按鈕
可以看見,請求幾次成功后,便顯示令牌過期,這是因為,為了測試方便,我們頒發(fā)令牌時有效期設(shè)置的10秒
4.在請求接口中不傳遞Token
重新登錄并點擊【請求后端受保護的接口】按鈕
到此這篇關(guān)于springboot+vue前后端分離項目中使用jwt實現(xiàn)登錄認證的文章就介紹到這了,更多相關(guān)springboot vue jwt登錄認證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot中@ConfigurationProperties注解的使用與源碼詳解
這篇文章主要介紹了SpringBoot中@ConfigurationProperties注解的使用與源碼詳解,@ConfigurationProperties注解用于自動配置綁定,可以將application.properties配置中的值注入到bean對象上,需要的朋友可以參考下2023-11-11AsyncHttpClient的ConnectionSemaphore方法源碼流程解讀
這篇文章主要為大家介紹了AsyncHttpClient的ConnectionSemaphore方法源碼流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12