SpringBoot登錄驗證token攔截器的實現(xiàn)
用戶訪問接口驗證,如果用戶沒有登錄,則不讓他訪問除登錄外的任何接口。
實現(xiàn)思路:
1.前端登錄,后端創(chuàng)建token(通過JWT這個依賴),返給前端
2.前端訪問其他接口,傳遞token,后端判斷token存在以或失效
3.失效或不存在,則返回失效提示,前端根據(jù)接口返回的失效提示,讓其跳轉(zhuǎn)到登錄界面
注解定義
定義2個注解,1個用于任何接口都能訪問,另外一個用于需要登錄才能訪問
調(diào)用都通過注解
package com.example.etf.story.tools; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface PassToken { boolean required() default true; }
登錄才能通過
package com.example.etf.story.tools; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface UserLoginToken { boolean required() default true; }
注解的作用說明
@Target代表此注解,能@到哪些代碼上
@Target
:注解的作用目標(biāo)
@Target(ElementType.TYPE)
——接口、類、枚舉、注解@Target(ElementType.FIELD)
——字段、枚舉的常量@Target(ElementType.METHOD)
——方法@Target(ElementType.PARAMETER)
——方法參數(shù)@Target(ElementType.CONSTRUCTOR)
——構(gòu)造函數(shù)@Target(ElementType.LOCAL_VARIABLE)
——局部變量@Target(ElementType.ANNOTATION_TYPE)
——注解@Target(ElementType.PACKAGE)
——包
@Retention
:注解的保留位置
RetentionPolicy.SOURCE
:這種類型的Annotations
只在源代碼級別保留,編譯時就會被忽略,在class
字節(jié)碼文件中不包含。RetentionPolicy.CLASS
:這種類型的Annotations
編譯時被保留,默認(rèn)的保留策略,在class
文件中存在,但JVM
將會忽略,運行時無法獲得。RetentionPolicy.RUNTIME
:這種類型的Annotations
將被JVM
保留,所以他們能在運行時被JVM
或其他使用反射機制的代碼所讀取和使用。@Document
:說明該注解將被包含在javadoc
中@Inherited
:說明子類可以繼承父類中的該注解
token生成與驗證
然后springBoot攔截器驗證token
攔截器定義
攔截器配置定義
攔截器攔截,除了登錄和發(fā)送短信,不攔截,其他都攔截
package com.example.etf.story.tools; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Resource private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { //注冊自己的攔截器,并設(shè)置攔截的請求路徑 //addPathPatterns為攔截此請求路徑的請求 //excludePathPatterns為不攔截此路徑的請求 registry.addInterceptor(loginInterceptor).addPathPatterns("/story/*").excludePathPatterns("/story/sendSMS") .excludePathPatterns("/story/signOrRegister"); } }
攔截的時候,調(diào)用的方法,給誰通過
其中service查詢數(shù)據(jù)庫,有沒有用戶,的方法要自己寫
攔截器的方法執(zhí)行類
package com.example.etf.story.tools; import com.auth0.jwt.JWT; import com.auth0.jwt.exceptions.JWTDecodeException; import com.example.etf.story.dao.R; import com.example.etf.story.paramer.UserInfoParam; import com.example.etf.story.service.TestClientService; import com.example.etf.story.service.TokenUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; @Slf4j @Component public class LoginInterceptor extends R implements HandlerInterceptor { /** * 目標(biāo)方法執(zhí)行前 * 該方法在控制器處理請求方法前執(zhí)行,其返回值表示是否中斷后續(xù)操作 * 返回 true 表示繼續(xù)向下執(zhí)行,返回 false 表示中斷后續(xù)操作 * * @return */ @Resource private TestClientService testClientService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("token");// 從 http 請求頭中取出 token // 如果不是映射到方法直接通過 if (!(handler instanceof HandlerMethod)) { return true; } HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); //檢查方法是否有passtoken注解,有則跳過認(rèn)證,直接通過 if (method.isAnnotationPresent(PassToken.class)) { PassToken passToken = method.getAnnotation(PassToken.class); if (passToken.required()) { return true; } } //檢查有沒有需要用戶權(quán)限的注解 if (method.isAnnotationPresent(UserLoginToken.class)) { UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class); if (userLoginToken.required()) { // 執(zhí)行認(rèn)證 if (token == null) { throw new RuntimeException("無token,請重新登錄"); } // 獲取 token 中的 user id String phone; try { phone = JWT.decode(token).getClaim("phone").asString(); } catch (JWTDecodeException j) { throw new RuntimeException("token不正確,請不要通過非法手段創(chuàng)建token"); } //查詢數(shù)據(jù)庫,看看是否存在此用戶,方法要自己寫 UserInfoParam userInfoParam = testClientService.selectUserByPhone(phone); if (userInfoParam == null) { throw new RuntimeException("用戶不存在,請重新登錄"); } // 驗證 token if (TokenUtils.verify(token)) { return true; } else { throw new RuntimeException("token過期或不正確,請重新登錄"); } } } throw new RuntimeException("沒有權(quán)限注解一律不通過"); } /** * 目標(biāo)方法執(zhí)行后 * 該方法在控制器處理請求方法調(diào)用之后、解析視圖之前執(zhí)行 * 可以通過此方法對請求域中的模型和視圖做進一步修改 */ @Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle執(zhí)行{}"); } /** * 頁面渲染后 * 該方法在視圖渲染結(jié)束后執(zhí)行 * 可以通過此方法實現(xiàn)資源清理、記錄日志信息等工作 */ @Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion執(zhí)行異常"); } }
注解使用
在controller層加入注解進行測試
返回值-全局異常類定義
加入全局,異常類,這樣當(dāng)異常,會返回你所指定的異常
package com.example.etf.story.tools; import com.alibaba.fastjson.JSONObject; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @ControllerAdvice public class GloablExceptionHandler { @ResponseBody @ExceptionHandler(Exception.class) public Object handleException(Exception e) { String msg = e.getMessage(); if (msg == null || msg.equals("")) { msg = "服務(wù)器出錯"; } JSONObject jsonObject = new JSONObject(); jsonObject.put("message", msg); jsonObject.put("status",500) return jsonObject; } }
各種測試
不傳token
成功
制造可行的假token
我們測試一下加token后的
因為數(shù)據(jù)庫里,我沒有插入,所以不存在,我們在隨便寫個token
偽造token測試
我們在試試
程序員使用:方法不加注解,測試
程序員使用:加上,調(diào)用通過,注解
我們試試,加上通過注解
拓展:從請求中獲取token
我們在試試從中獲取token
參考文章:
SpringBoot集成JWT實現(xiàn)token驗證 - 簡書
springboot對請求的接口實現(xiàn)token攔截以及參數(shù)校驗_kotomeli的博客-CSDN博客_springboot攔截請求參數(shù)
到此這篇關(guān)于SpringBoot登錄驗證token攔截器的實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot token攔截器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot實現(xiàn)token驗證登陸狀態(tài)的示例代碼
- SpringBoot整合JWT(JSON?Web?Token)生成token與驗證的流程及示例
- springboot+shiro+jwtsession和token進行身份驗證和授權(quán)
- SpringBoot集成JWT實現(xiàn)Token登錄驗證的示例代碼
- 實戰(zhàn)SpringBoot集成JWT實現(xiàn)token驗證
- Springboot 如何實現(xiàn)filter攔截token驗證和跨域
- SpringBoot整合JWT框架,解決Token跨域驗證問題
- SpringBoot集成JWT實現(xiàn)token驗證的流程
- SpringBoot下token短信驗證登入登出權(quán)限操作(token存放redis,ali短信接口)
- Spring boot+VUE實現(xiàn)token驗證的示例代碼
相關(guān)文章
SpringBoot集成企業(yè)微信開發(fā)的實現(xiàn)
本文將詳細(xì)介紹如何使用?Spring?Boot?集成企業(yè)微信開發(fā),通過企業(yè)微信?API?可以實現(xiàn)企業(yè)內(nèi)部的一些自動化業(yè)務(wù)流程,提高工作效率,感興趣的可以了解一下2023-07-07httpclient 請求http數(shù)據(jù),json轉(zhuǎn)map的實例
下面小編就為大家?guī)硪黄猦ttpclient 請求http數(shù)據(jù),json轉(zhuǎn)map的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12