springboot+vue前后端分離項(xiàng)目中使用jwt實(shí)現(xiàn)登錄認(rèn)證
一、后端代碼
1.響應(yīng)工具類(lèi)
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");
// 解決跨域問(wèn)題 設(shè)置跨域頭
response.setHeader("Access-Control-Allow-Origin","*");
// 輸出流
PrintWriter out = response.getWriter();
// 輸出
out.write(new ObjectMapper().writeValueAsString(rm));
// 關(guān)閉流
out.close();
}
}
2.jwt工具類(lèi)
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è)置多個(gè)自定義數(shù)據(jù) 位置只能放在前面,如果放在后面,那前面的載荷會(huì)失效
.setId(UUID.randomUUID().toString())// 唯一標(biāo)識(shí)
.setIssuer("liukang")// 簽發(fā)人
.setIssuedAt(new Date())// 簽發(fā)時(shí)間
.setSubject("jwtDemo")// 主題
.setExpiration(new Date(System.currentTimeMillis()+expire))//過(guò)期時(shí)間
// 簽名
.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())// 唯一標(biāo)識(shí)
.setIssuer("liukang")// 簽發(fā)人
.setIssuedAt(new Date())// 簽發(fā)時(shí)間
.setSubject("jwtDemo")// 主題
.setExpiration(new Date(System.currentTimeMillis()+expire))//過(guò)期時(shí)間
// 簽名
.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.登錄用戶(hù)實(shí)體類(lèi)
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.測(cè)試接口
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","測(cè)試請(qǐng)求接口成功!");
}
}
6.過(guò)濾器
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過(guò)濾器
* @Date 2024/6/10 9:46
* @Author liukang
**/
@WebFilter(urlPatterns = "/*") // 過(guò)濾所有路徑
public class JwtFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 得到兩個(gè)對(duì)象
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//直接放行
if(HttpMethod.OPTIONS.toString().equals(request.getMethod())){
filterChain.doFilter(request,response);
return;
}
String requestURI = request.getRequestURI(); // 不含主機(jī)和端口號(hào)
if(requestURI.contains("/login")){
filterChain.doFilter(request,response);
return;
}
// 得到請(qǐng)求頭的信息(accessToken)
String token = request.getHeader("accessToken");
if(!StringUtils.hasText(token)){
//響應(yīng)前端錯(cuò)誤的消息提示
ResponseModel responseModel = new ResponseModel(500,"failure","令牌缺失!");
ResponseUtil.write(responseModel,response);
return;
}
// 解析Token信息
try {
JwtUtil.parseToken(token);
}catch (Exception e){
//響應(yīng)前端錯(cuò)誤的消息提示
ResponseModel responseModel = new ResponseModel(401,"failure","令牌過(guò)期!");
ResponseUtil.write(responseModel,response);
return;
}
filterChain.doFilter(request,response);
}
}
7.啟動(dòng)類(lèi)
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")// 這個(gè)包下激活WebFilter這個(gè)注解
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
二、前端代碼
登錄頁(yè)
<template>
<div class="hello">
<form>
用戶(hù)名:<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 頁(yè)面
<template>
<div>
<button @click="test">請(qǐng)求受保護(hù)的接口</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.點(diǎn)擊登錄后,后端給前端辦法jwt令牌,前端將其存入sessionStorage中

2.點(diǎn)擊【請(qǐng)求后端受保護(hù)的接口】按鈕

3.繼續(xù)多次點(diǎn)擊【請(qǐng)求后端受保護(hù)的接口】按鈕

可以看見(jiàn),請(qǐng)求幾次成功后,便顯示令牌過(guò)期,這是因?yàn)椋瑸榱藴y(cè)試方便,我們頒發(fā)令牌時(shí)有效期設(shè)置的10秒

4.在請(qǐng)求接口中不傳遞Token

重新登錄并點(diǎn)擊【請(qǐng)求后端受保護(hù)的接口】按鈕

到此這篇關(guān)于springboot+vue前后端分離項(xiàng)目中使用jwt實(shí)現(xiàn)登錄認(rèn)證的文章就介紹到這了,更多相關(guān)springboot vue jwt登錄認(rèn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
推薦一款I(lǐng)ntelliJ IDEA提示快捷鍵的Key Promoter X插件
今天小編就為大家分享一篇關(guān)于IntelliJ IDEA提示快捷鍵的Key Promoter X插件,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10
SpringBoot整合MyBatis-Plus樂(lè)觀鎖不生效的問(wèn)題及解決方法
這篇文章主要介紹了SpringBoot整合MyBatis-Plus樂(lè)觀鎖不生效的問(wèn)題解決方案,通過(guò)實(shí)例代碼介紹了SpringBoot各個(gè)層次的操作,需要的朋友可以參考下2022-04-04
SpringBoot實(shí)現(xiàn)定時(shí)發(fā)送郵件的三種方法案例詳解
這篇文章主要介紹了SpringBoot三種方法實(shí)現(xiàn)定時(shí)發(fā)送郵件的案例,Spring框架的定時(shí)任務(wù)調(diào)度功能支持配置和注解兩種方式Spring?Boot在Spring框架的基礎(chǔ)上實(shí)現(xiàn)了繼承,并對(duì)其中基于注解方式的定時(shí)任務(wù)實(shí)現(xiàn)了非常好的支持,本文給大家詳細(xì)講解,需要的朋友可以參考下2023-03-03
在Java中輕松將HTML格式文本轉(zhuǎn)換為純文本的方法示例(保留換行)
這篇文章主要介紹了在Java中輕松將HTML格式文本轉(zhuǎn)換為純文本的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Java中Maven項(xiàng)目導(dǎo)出jar包配置的示例代碼
這篇文章主要介紹了Java中Maven項(xiàng)目導(dǎo)出jar包配置的示例代碼,需要的朋友可以參考下2018-11-11
springboot+websocket實(shí)現(xiàn)并發(fā)搶紅包功能
本文主要介紹了springboot+websocket實(shí)現(xiàn)并發(fā)搶紅包功能,主要包含了4種步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12
Java在Linux上調(diào)用FFmpeg實(shí)現(xiàn)視頻截圖的完整指南
在Linux環(huán)境下使用Java與FFmpeg命令交互進(jìn)行視頻截圖是多媒體處理中的常見(jiàn)任務(wù),本文介紹了如何在Java程序中執(zhí)行FFmpeg命令,通過(guò)提供具體代碼示例來(lái)展示在特定時(shí)間點(diǎn)獲取視頻靜態(tài)圖像的方法,需要的朋友可以參考下2025-08-08

