一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SpringBoot使用自定義注解實現(xiàn)權限攔截的示例

SpringBoot使用自定義注解實現(xiàn)權限攔截的示例

2021-01-13 14:59小雨轉暴雨 Java教程

本篇文章主要介紹了SpringBoot使用自定義注解實現(xiàn)權限攔截的示例,具有一定的參考價值,有興趣的可以了解一下

本文介紹了SpringBoot使用自定義注解實現(xiàn)權限攔截的示例,分享給大家,具體如下:

HandlerInterceptor(處理器攔截器)

常見使用場景

  • 日志記錄: 記錄請求信息的日志, 以便進行信息監(jiān)控, 信息統(tǒng)計, 計算PV(page View)等
  • 性能監(jiān)控:
  • 權限檢查:
  • 通用行為:

使用自定義注解實現(xiàn)權限攔截

首先HandlerInterceptor了解

在HandlerInterceptor中有三個方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
public interface HandlerInterceptor {
 
  // 在執(zhí)行目標方法之前執(zhí)行
  boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)throws Exception;
 
  // 執(zhí)行目標方法之后執(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í)行順序, 測試及測試結果如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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");
  }
}

結果:

preHandler
postHandler
afterCompletion

如何配置攔截器后面講:

下面來講講這個攔截器是攔截的什么?

方法攔截器HandlerInterceptor

我們使用SpringMVC都知道SpringMVC是基于方法的請求處理, 和Struts2有明顯區(qū)別(我是這么理解的), 并且Controller是單例模式, 所有請求都是從DispatcherServlet來調用請求url對應的方法的(處理器映射器的功能), 那么它是一個方法攔截器, 如何知道呢?

?
1
2
3
4
5
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  System.out.println(handler.getClass());
  return true;
}

執(zhí)行結果:

class org.springframework.web.method.HandlerMethod

已經(jīng)看到攔截器如何工作, 并且知道它是方法級別的攔截器, 那么接下來看看如何配置攔截器, 讓它在服務器運行期間起作用

實現(xiàn)HandlerInterceptor

實現(xiàn)HandlerInterceptor接口或者繼承HandlerInterceptorAdapter類
HandlerInterceptorAdapter適配器是對HandlerInterceptor接口做了默認實現(xiàn), 這種適配器模式, 是為了方便開發(fā)者只去想要復寫方法, 其他方法采取默認措施.

上面的TestInterceptor就是一個Demo, 具體可以按需求在我們想要攔截的位置進行相應的邏輯處理

配置攔截器

從Spring4.x開始, 就支持注解配置具體是使用@Configuration注解標注一個普通類, 使該類成為配置類, 可以在該類中定義Bean, 以及注入一些配置參數(shù)等.

首先, 我們要配置攔截器,就需要想SpringMvc的攔截鏈中取注入我們的攔截器, 這樣才能請求進來時去攔截我們想要攔截的請求, 所以, 需要我們新建一個普通類, 使用@Configuration注解標注在類名上, 并且讓該類繼承WebMvcConfigurerAdapter,為什么不實現(xiàn)WebMvcConfigurer接口呢? 因為方法太多,我們不需要復寫其中所有方法...

下面讓我們新建一個配置類, 來配置我們的攔截器

?
1
2
3
4
5
6
7
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
 
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**");
  }
}

復寫addInterceptors之后, 當我們的服務器啟動時, 會自動調用這個方法, 參數(shù)怎么傳我們都不用管(目前是java初級階段, 沒空研究Spring深層原理), 我們只要知道這個方法一定會被調用就行了.

我們直接new一個自定義攔截器, 注冊到整個攔截鏈中, 并且制定攔截路徑, 這樣當滿足請求url攔截配置時, 我們的自定義攔截器就會執(zhí)行相應的方法了.

攔截方法是非常靈的, 除了攔截配置的, 也可以攔截非匹配的, 也可以根據(jù)正則表達式攔截請求

至此, 我們的攔截器就完成了, 接下來自定義權限相關注解

自定義權限注解

定義一個@interface類

?
1
2
3
4
5
6
7
8
9
10
11
12
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Access {
 
  String[] value() default {};
 
  String[] authorities() default {};
 
  String[] roles() default {};
 
}

@Target注解是標注這個類它可以標注的位置:

常用的元素類型(ElementType):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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 */
  // 聲明在構造方法上
  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注解表示的是本注解(標注這個注解的注解保留時期)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public enum RetentionPolicy {
  /**
   * Annotations are to be discarded by the compiler.
   */
  // 源代碼時期
  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é)碼時期, 編譯之后
  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
   */
   // 運行時期, 也就是一直保留, 通常也都用這個
  RUNTIME
}

@Documented是否生成文檔的標注, 也就是生成接口文檔是, 是否生成注解文檔

注解說完了, 下面需要到對應的controller的方法中取添加注解, 配置該方法允許的權限

在方法上配置權限

?
1
2
3
4
5
6
7
8
9
10
@RestController
public class HelloController {
 
  @RequestMapping(value = "/admin", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET)
  // 配置注解權限, 允許身份為admin, 或者說允許權限為admin的人訪問
  @Access(authorities = {"admin"})
  public String hello() {
    return "Hello, admin";
  }
}

編寫權限邏輯

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 自定義一個權限攔截器, 繼承HandlerInterceptorAdapter類
public class AuthenticationInterceptor extends HandlerInterceptorAdapter {
 
  // 在調用方法之前執(zhí)行攔截
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 將handler強轉為HandlerMethod, 前面已經(jīng)證實這個handler就是HandlerMethod
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    // 從方法處理器中獲取出要調用的方法
    Method method = handlerMethod.getMethod();
    // 獲取出方法上的Access注解
    Access access = method.getAnnotation(Access.class);
    if (access == null) {
    // 如果注解為null, 說明不需要攔截, 直接放過
      return true;
    }
    if (access.authorities().length > 0) {
      // 如果權限配置不為空, 則取出配置值
      String[] authorities = access.authorities();
      Set<String> authSet = new HashSet<>();
      for (String authority : authorities) {
      // 將權限加入一個set集合中
        authSet.add(authority);
      }
      // 這里我為了方便是直接參數(shù)傳入權限, 在實際操作中應該是從參數(shù)中獲取用戶Id
      // 到數(shù)據(jù)庫權限表中查詢用戶擁有的權限集合, 與set集合中的權限進行對比完成權限校驗
      String role = request.getParameter("role");
      if (StringUtils.isNotBlank(role)) {
        if (authSet.contains(role)) {
        // 校驗通過返回true, 否則攔截請求
          return true;
        }
      }
    }
    // 攔截之后應該返回公共結果, 這里沒做處理
    return false;
  }
 
}

至此, 我們啟動服務器, 訪問接口, 就能看到效果, 這里不做示范了

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.jianshu.com/p/43c97352aa1e

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: japanese人妖xvideos | 黑人巨荃大战乌克兰美女 | 久久伊人精品青青草原2021 | 91九色porny国产美女一区 | 短篇同学新婚h系列小说 | 国产日韩欧美在线一区二区三区 | 天天操天天干天天舔 | 精品一二三区久久AAA片 | 国产人成激情视频在线观看 | 91久久精品国产亚洲 | 国产成人精视频在线观看免费 | 日本漫画大全之工之口 | 国产欧美日韩精品一区二区三区 | 99热综合在线 | 日韩一区二区三区免费 | 午夜一区二区福利视频在线 | 九色PORNY丨视频入口 | 女人爽到喷水的视频免费看 | 四虎在线永久视频观看 | 男人天堂999 | 99久久国产亚洲综合精品 | 色噜噜亚洲男人的天堂www | 無码一区中文字幕少妇熟女网站 | 欧美日韩中文国产一区二区三区 | 欧美一级二级片 | 男男playh片在线观看 | 日韩一本在线 | 国产极品精频在线观看 | 亚洲精品一区二区久久久久 | 男人的影院| 亚洲精品卡一卡2卡3卡4卡 | 亚洲激情欧美 | poverty中国老妇人 | 久久性生大片免费观看性 | 日本在线观看视频网站 | 午夜影视在线观看 | 无人视频在线观看完整版高清 | 亚洲 日本 天堂 国产 在线 | 情乱奶水欲 | 午夜影院c绿象 | 美女gif趴跪式抽搐动态图 |