SpringBoot使用自定義注解實(shí)現(xiàn)權(quán)限攔截的示例
本文介紹了SpringBoot使用自定義注解實(shí)現(xiàn)權(quán)限攔截的示例,分享給大家,具體如下:
HandlerInterceptor(處理器攔截器)
常見使用場景
- 日志記錄: 記錄請求信息的日志, 以便進(jìn)行信息監(jiān)控, 信息統(tǒng)計(jì), 計(jì)算PV(page View)等
- 性能監(jiān)控:
- 權(quán)限檢查:
- 通用行為:
使用自定義注解實(shí)現(xiàn)權(quán)限攔截
首先HandlerInterceptor了解
在HandlerInterceptor中有三個(gè)方法:
public interface HandlerInterceptor {
// 在執(zhí)行目標(biāo)方法之前執(zhí)行
boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)throws Exception;
// 執(zhí)行目標(biāo)方法之后執(zhí)行
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;
// 在請求已經(jīng)返回之后執(zhí)行
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;
}
在以上注釋中已經(jīng)寫明執(zhí)行順序, 測試及測試結(jié)果如下:
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandler");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandler");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
結(jié)果:
preHandler
postHandler
afterCompletion
如何配置攔截器后面講:
下面來講講這個(gè)攔截器是攔截的什么?
方法攔截器HandlerInterceptor
我們使用SpringMVC都知道SpringMVC是基于方法的請求處理, 和Struts2有明顯區(qū)別(我是這么理解的), 并且Controller是單例模式, 所有請求都是從DispatcherServlet來調(diào)用請求url對應(yīng)的方法的(處理器映射器的功能), 那么它是一個(gè)方法攔截器, 如何知道呢?
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(handler.getClass());
return true;
}
執(zhí)行結(jié)果:
class org.springframework.web.method.HandlerMethod
已經(jīng)看到攔截器如何工作, 并且知道它是方法級(jí)別的攔截器, 那么接下來看看如何配置攔截器, 讓它在服務(wù)器運(yùn)行期間起作用
實(shí)現(xiàn)HandlerInterceptor
實(shí)現(xiàn)HandlerInterceptor接口或者繼承HandlerInterceptorAdapter類
HandlerInterceptorAdapter適配器是對HandlerInterceptor接口做了默認(rèn)實(shí)現(xiàn), 這種適配器模式, 是為了方便開發(fā)者只去想要復(fù)寫方法, 其他方法采取默認(rèn)措施.
上面的TestInterceptor就是一個(gè)Demo, 具體可以按需求在我們想要攔截的位置進(jìn)行相應(yīng)的邏輯處理
配置攔截器
從Spring4.x開始, 就支持注解配置具體是使用@Configuration注解標(biāo)注一個(gè)普通類, 使該類成為配置類, 可以在該類中定義Bean, 以及注入一些配置參數(shù)等.
首先, 我們要配置攔截器,就需要想SpringMvc的攔截鏈中取注入我們的攔截器, 這樣才能請求進(jìn)來時(shí)去攔截我們想要攔截的請求, 所以, 需要我們新建一個(gè)普通類, 使用@Configuration注解標(biāo)注在類名上, 并且讓該類繼承WebMvcConfigurerAdapter,為什么不實(shí)現(xiàn)WebMvcConfigurer接口呢? 因?yàn)榉椒ㄌ?我們不需要復(fù)寫其中所有方法...
下面讓我們新建一個(gè)配置類, 來配置我們的攔截器
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**");
}
}
復(fù)寫addInterceptors之后, 當(dāng)我們的服務(wù)器啟動(dòng)時(shí), 會(huì)自動(dòng)調(diào)用這個(gè)方法, 參數(shù)怎么傳我們都不用管(目前是java初級(jí)階段, 沒空研究Spring深層原理), 我們只要知道這個(gè)方法一定會(huì)被調(diào)用就行了.
我們直接new一個(gè)自定義攔截器, 注冊到整個(gè)攔截鏈中, 并且制定攔截路徑, 這樣當(dāng)滿足請求url攔截配置時(shí), 我們的自定義攔截器就會(huì)執(zhí)行相應(yīng)的方法了.
攔截方法是非常靈的, 除了攔截配置的, 也可以攔截非匹配的, 也可以根據(jù)正則表達(dá)式攔截請求
至此, 我們的攔截器就完成了, 接下來自定義權(quán)限相關(guān)注解
自定義權(quán)限注解
定義一個(gè)@interface類
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Access {
String[] value() default {};
String[] authorities() default {};
String[] roles() default {};
}
@Target注解是標(biāo)注這個(gè)類它可以標(biāo)注的位置:
常用的元素類型(ElementType):
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
// TYPE類型可以聲明在類上或枚舉上或者是注解上
TYPE,
/** Field declaration (includes enum constants) */
// FIELD聲明在字段上
FIELD,
/** Method declaration */
// 聲明在方法上
METHOD,
/** Formal parameter declaration */
// 聲明在形參列表中
PARAMETER,
/** Constructor declaration */
// 聲明在構(gòu)造方法上
CONSTRUCTOR,
/** Local variable declaration */
// 聲明在局部變量上
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Retention注解表示的是本注解(標(biāo)注這個(gè)注解的注解保留時(shí)期)
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
// 源代碼時(shí)期
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
// 字節(jié)碼時(shí)期, 編譯之后
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
// 運(yùn)行時(shí)期, 也就是一直保留, 通常也都用這個(gè)
RUNTIME
}
@Documented是否生成文檔的標(biāo)注, 也就是生成接口文檔是, 是否生成注解文檔
注解說完了, 下面需要到對應(yīng)的controller的方法中取添加注解, 配置該方法允許的權(quán)限
在方法上配置權(quán)限
@RestController
public class HelloController {
@RequestMapping(value = "/admin", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET)
// 配置注解權(quán)限, 允許身份為admin, 或者說允許權(quán)限為admin的人訪問
@Access(authorities = {"admin"})
public String hello() {
return "Hello, admin";
}
}
編寫權(quán)限邏輯
// 自定義一個(gè)權(quán)限攔截器, 繼承HandlerInterceptorAdapter類
public class AuthenticationInterceptor extends HandlerInterceptorAdapter {
// 在調(diào)用方法之前執(zhí)行攔截
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 將handler強(qiáng)轉(zhuǎn)為HandlerMethod, 前面已經(jīng)證實(shí)這個(gè)handler就是HandlerMethod
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 從方法處理器中獲取出要調(diào)用的方法
Method method = handlerMethod.getMethod();
// 獲取出方法上的Access注解
Access access = method.getAnnotation(Access.class);
if (access == null) {
// 如果注解為null, 說明不需要攔截, 直接放過
return true;
}
if (access.authorities().length > 0) {
// 如果權(quán)限配置不為空, 則取出配置值
String[] authorities = access.authorities();
Set<String> authSet = new HashSet<>();
for (String authority : authorities) {
// 將權(quán)限加入一個(gè)set集合中
authSet.add(authority);
}
// 這里我為了方便是直接參數(shù)傳入權(quán)限, 在實(shí)際操作中應(yīng)該是從參數(shù)中獲取用戶Id
// 到數(shù)據(jù)庫權(quán)限表中查詢用戶擁有的權(quán)限集合, 與set集合中的權(quán)限進(jìn)行對比完成權(quán)限校驗(yàn)
String role = request.getParameter("role");
if (StringUtils.isNotBlank(role)) {
if (authSet.contains(role)) {
// 校驗(yàn)通過返回true, 否則攔截請求
return true;
}
}
}
// 攔截之后應(yīng)該返回公共結(jié)果, 這里沒做處理
return false;
}
}
至此, 我們啟動(dòng)服務(wù)器, 訪問接口, 就能看到效果, 這里不做示范了
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringBoot配置攔截器的示例
- SpringBoot之HandlerInterceptor攔截器的使用詳解
- 解決Springboot @WebFilter攔截器未生效問題
- springboot攔截器過濾token,并返回結(jié)果及異常處理操作
- SpringBoot攔截器如何獲取http請求參數(shù)
- SpringBoot攔截器實(shí)現(xiàn)登錄攔截的方法示例
- SpringBoot基于自定義注解實(shí)現(xiàn)切面編程
- SpringBoot中自定義注解實(shí)現(xiàn)參數(shù)非空校驗(yàn)的示例
- java SpringBoot自定義注解,及自定義解析器實(shí)現(xiàn)對象自動(dòng)注入操作
- SpringBoot 攔截器和自定義注解判斷請求是否合法
相關(guān)文章
ThreadLocal導(dǎo)致JVM內(nèi)存泄漏原因探究
ThreadLocal是JDK提供的線程本地變量機(jī)制,但若使用不當(dāng)可能導(dǎo)致內(nèi)存泄漏。正確的使用方式是在使用完后及時(shí)remove,或者使用弱引用等手段避免強(qiáng)引用導(dǎo)致的內(nèi)存泄漏。在多線程編程中,合理使用ThreadLocal可以提高并發(fā)性能,但也需要注意其潛在的內(nèi)存泄漏問題2023-04-04
3分鐘純 Java 注解搭個(gè)管理系統(tǒng)的示例代碼
這篇文章主要介紹了3分鐘純 Java 注解搭個(gè)管理系統(tǒng)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Java解決xss轉(zhuǎn)義導(dǎo)致轉(zhuǎn)碼的問題
跨站腳本攻擊XSS是最普遍的Web應(yīng)用安全漏洞,本文主要介紹了Java解決xss轉(zhuǎn)義導(dǎo)致轉(zhuǎn)碼的問題,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08
SpringBoot不讀取bootstrap.yml/properties文件問題
這篇文章主要介紹了SpringBoot不讀取bootstrap.yml/properties文件問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
spring-mvc/springboot使用MockMvc對controller進(jìn)行測試
這篇文章主要介紹了spring-mvc/springboot使用MockMvc對controller進(jìn)行測試,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11
eclipse springboot工程打war包方法及再Tomcat中運(yùn)行的方法
這篇文章主要介紹了eclipse springboot工程打war包方法及再Tomcat中運(yùn)行的方法,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
springboot如何查找配置文件路徑的順序和其優(yōu)先級(jí)別
此文是在工作中遇到的關(guān)于springboot配置文件的問題,在網(wǎng)上查閱資料和自己測試之后記錄的,以便日后查閱。希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08

