Spring boot+VUE實(shí)現(xiàn)token驗(yàn)證的示例代碼
一、 步驟
Vue+Spring Boot實(shí)現(xiàn)token認(rèn)證主要可分為六步:
1.前端登錄,post用戶名和密碼到后端。
2.后端驗(yàn)證用戶名和密碼,若通過,生成一個(gè)token返回給前端。
3.前端拿到token用vuex和localStorage管理,登錄成功進(jìn)入首頁。
4.之后前端每一次權(quán)限操作如跳轉(zhuǎn)路由,都需要判斷是否存在token,若不存在,跳轉(zhuǎn)至登錄頁。
5.前端之后的每一個(gè)對(duì)后端的請(qǐng)求都要在請(qǐng)求頭上帶上token,后端查看請(qǐng)求頭是否有token,拿到token檢查是否過期,返回對(duì)應(yīng)狀態(tài)給前端。(通常失敗返回401)
6.若token已過期,清除token信息,跳轉(zhuǎn)至登錄頁。
二、后端
1.導(dǎo)依賴
<!-- jwt.token要用到的-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
2.添加token工具類
.withClaim(“Username”, staff.getUsername())
我這個(gè)項(xiàng)目沒有用戶密碼,所以我這里只用一個(gè)Username,如果有密碼的話可以加多一行,比如說:
.withClaim(“Password”, staff.getPassword())
package com.xfish.employeeManagement.token;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.xfish.employeeManagement.pojo.staff;
import java.util.Date;
public class TokenUtil {
private static final long EXPIRE_TIME= 10*60*60*1000; //十小時(shí)
private static final String TOKEN_SECRET="123456"; //密鑰鹽
/**
* 簽名生成
* @param staff
* @return
*/
public static String sign(staff staff){
String token = null;
try {
Date expiresAt = new Date(System.currentTimeMillis() + EXPIRE_TIME);
token = JWT.create()
.withIssuer("auth0")
.withClaim("Username", staff.getUsername())
// .withAudience(staff.getUsername())
.withExpiresAt(expiresAt)
// 使用了HMAC256加密算法。
.sign(Algorithm.HMAC256(TOKEN_SECRET));
} catch (Exception e){
e.printStackTrace();
}
return token;
}
/**
* 簽名驗(yàn)證
* @param token
* @return
*/
public static boolean verify(String token){
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
DecodedJWT jwt = verifier.verify(token);
System.err.println("認(rèn)證通過:");
System.err.println("Username: " + jwt.getClaim("Username").asString());
System.err.println("過期時(shí)間: " + jwt.getExpiresAt());
return true;
} catch (Exception e){
return false;
}
}
}
3.添加攔截器
這個(gè)攔截器主要的功能就是,把一些沒有token的請(qǐng)求攔截下來并返回錯(cuò)誤信息,有token就可以直接通過
package com.xfish.employeeManagement.Interceptor;
import com.alibaba.fastjson.JSONObject;
import com.xfish.employeeManagement.token.TokenUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{
if(request.getMethod().equals("OPTIONS")){
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
response.setCharacterEncoding("utf-8");
String token = request.getHeader("token"); //前端vue將token添加在請(qǐng)求頭中
// System.err.println(request.getHeader());
if(token != null){
boolean result = TokenUtil.verify(token);
if(result){
System.out.println("通過攔截器");
return true;
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
try{
JSONObject json = new JSONObject();
json.put("msg","token verify fail");
json.put("code","50000");
response.getWriter().append(json.toJSONString());
System.out.println("認(rèn)證失敗,未通過攔截器");
}catch (Exception e){
e.printStackTrace();
response.sendError(500);
return false;
}
return false;
}
}
4.配置跨域,并處理請(qǐng)求
注意:這邊攔截的是后端的接口,不是前端的,
在中’ /** ‘無論是restful的,還是后面有一大長串地址都可以識(shí)別到
excludePath.add(“/toLogin/**”);
package com.xfish.employeeManagement.config;
import com.xfish.employeeManagement.Interceptor.TokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 開啟跨域
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
// 設(shè)置允許跨域的路由
registry.addMapping("/**")
// 設(shè)置允許跨域請(qǐng)求的域名
.allowedOriginPatterns("*")
// 設(shè)置允許的方法
.allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")
// 是否允許攜帶cookie參數(shù)
.allowCredentials(true)
// 設(shè)置允許的方法
.allowedMethods("*")
// 跨域允許時(shí)間
.maxAge(4600);
}
private TokenInterceptor tokenInterceptor;
//構(gòu)造方法
public WebMvcConfig(TokenInterceptor tokenInterceptor){
this.tokenInterceptor = tokenInterceptor;
}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer){
configurer.setTaskExecutor(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(3)));
configurer.setDefaultTimeout(30000);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> excludePath = new ArrayList<>();
//排除攔截,除了注冊登錄(此時(shí)還沒token),其他都攔截
// excludePath.add(""); //登錄
excludePath.add("/toLogin/**"); //登錄
// excludePath.add("/admin/login"); //注冊
// excludePath.add("/**");
excludePath.add("/img/**"); //靜態(tài)資源
excludePath.add("/song/**"); //靜態(tài)資源
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(excludePath);
WebMvcConfigurer.super.addInterceptors(registry);
}
}
5.登錄接口
@GetMapping("/toLogin/{username}")
public Object toLogin(@PathVariable("username") String username){
staff staff = staffService.queryStaffDataByName(username);
JSONObject jsonObject = new JSONObject();
if(staff!=null){
String token = TokenUtil.sign(staff);
jsonObject.put("token",token);
jsonObject.put("staff",staff);
jsonObject.put("msg","登錄成功");
jsonObject.put("code",200);
}else {
jsonObject.put("msg","賬號(hào)或密碼錯(cuò)誤");
jsonObject.put("code",500);
}
return jsonObject;
}
三、前端
1.main.js配置
添加路由前置守衛(wèi)beforeEach攔截請(qǐng)求,2.在axios中添加請(qǐng)求攔截器:
//路由全局前置守衛(wèi)
router.beforeEach((to,from,next) => {
// if(to.path === '/register' || to.path === '/login' || to.path === '/'){ //若是進(jìn)入登錄與注冊頁面 ==> pass
if(to.path === '/register' || to.path === '' || to.path === '/'){
next()
}else{
let userToken = localStorage.getItem('token');
// console.log("Token為:"+userToken);
if(userToken == null || userToken == ''){
alert("無權(quán)限,請(qǐng)先登錄!");
return next('/');
}else{
next();
}
}
}),
//請(qǐng)求攔截器 在請(qǐng)求頭中加token
axios.interceptors.request.use(
config => { // 將獲取到的token設(shè)置給header中的token
if(localStorage.getItem('token')){
config.headers.token = localStorage.getItem('token');
}
return config;
},
error => {
return Promise.reject(error);
}
)
2.配置Vuex
在配置前記得一定要下載Vuex的依賴
cnpm install vuex --save
vuex的使用方式(可以不看)
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
user: localStorage.getItem('staff') ? localStorage.getItem('staff') : null,
//若localSorage存在token,將值賦給Vuex.state.token
token: localStorage.getItem('token') ? localStorage.getItem('token') : null
},
mutations: {
setUsername(state, staff) {
state.staff = staff
// JSON.stringify(ary)
//將staff存成JSON格式
localStorage.setItem('staff', JSON.stringify(staff))
},
setToken(state, token) {
localStorage.setItem('token', token)
state.token = token
},
//我頁面中寫了退出登錄的按鈕所以補(bǔ)了一個(gè)logout用來清空localStorage中的數(shù)據(jù)
logout(state) {
localStorage.removeItem('token')
state.token = null
localStorage.removeItem('staff')
state.setUsername = null
//我寫的RSA加密需向后端獲取公鑰,為了方便我在拿到公鑰后直接存入localStorage中,所以在這里也要清空
localStorage.removeItem('publickey')
state.publickey=null
}
}
})
3.登錄方法
記得一定要導(dǎo)包
import store from ‘…/store/index.js’
import store from '../store/index.js'
export default {
data() {
return {
ruleForm: { pass: '', username: ''},
staff:null,
}
},
methods: {
}
submitForm() {
var vm=this;
vm.axios.get('http://localhost:8090/toLogin/'+this.ruleForm.username+''
).then(function (response) {
console.log(response.data.staff)
if(response.data.code == 200){//將token和user保存到localStorage中
store.commit('setToken',response.data.token)
store.commit('setUsername',response.data.staff)
//跳轉(zhuǎn)到登錄成功后的頁面
console.log("========"+response.data.msg)
vm.$router.push('/index')
//獲取本地存儲(chǔ)中的staff
vm.staff=JSON.parse(localStorage.getItem('staff'))
console.log(vm.staff);
}
else{
alert(response.data.msg)
}
}).catch(function (e) {
console.log(e)
})
}
4.退出登錄
退出登錄方法,記得一定要導(dǎo)包
import store from ‘…/store/index.js’
loginOut(){
store.commit('logout')
}
Spring boot+VUE為什么不用session,
因?yàn)閟ession是存在與服務(wù)器的,跨域session是會(huì)變的。
到此這篇關(guān)于Spring boot+VUE實(shí)現(xiàn)token驗(yàn)證的示例代碼的文章就介紹到這了,更多相關(guān)Spring boot VUE token驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot實(shí)現(xiàn)token驗(yàn)證登陸狀態(tài)的示例代碼
- SpringBoot整合JWT(JSON?Web?Token)生成token與驗(yàn)證的流程及示例
- springboot+shiro+jwtsession和token進(jìn)行身份驗(yàn)證和授權(quán)
- SpringBoot集成JWT實(shí)現(xiàn)Token登錄驗(yàn)證的示例代碼
- SpringBoot登錄驗(yàn)證token攔截器的實(shí)現(xiàn)
- 實(shí)戰(zhàn)SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證
- Springboot 如何實(shí)現(xiàn)filter攔截token驗(yàn)證和跨域
- SpringBoot整合JWT框架,解決Token跨域驗(yàn)證問題
- SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證的流程
- SpringBoot下token短信驗(yàn)證登入登出權(quán)限操作(token存放redis,ali短信接口)
相關(guān)文章
劍指Offer之Java算法習(xí)題精講字符串操作與數(shù)組及二叉搜索樹
跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化2022-03-03
Java之Spring注解配置bean實(shí)例代碼解析
這篇文章主要介紹了Java之Spring注解配置bean實(shí)例代碼解析,具有一定參考價(jià)值,文中還有有關(guān)Spring學(xué)習(xí)的資料下載鏈接及相關(guān)內(nèi)容推薦,需要的朋友可以了解下。2017-09-09
java新增關(guān)聯(lián)的三張表,每張表要求都插入集合,代碼實(shí)現(xiàn)方式
這篇文章主要介紹了java新增關(guān)聯(lián)的三張表,每張表要求都插入集合,代碼實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Mybatis執(zhí)行Update返回行數(shù)為負(fù)數(shù)的問題
這篇文章主要介紹了Mybatis執(zhí)行Update返回行數(shù)為負(fù)數(shù)的問題,具有很好的參考價(jià)值,希望大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
redis.clients.jedis.exceptions.JedisMovedDataException異常解決
redis.clients.jedis.exceptions.JedisMovedDataException?異常是在使用?Jedis?客戶端與?Redis?集群進(jìn)行交互時(shí)發(fā)生的,下面就來介紹一下解決方法,感興趣的可以了解一下2024-05-05
Java通過Socket實(shí)現(xiàn)簡單多人聊天室
這篇文章主要為大家詳細(xì)介紹了Java通過Socket實(shí)現(xiàn)簡單多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04

