SpringBoot独自の注釈を使用して権限ブロックを実現する例


本文では、SpringBootがユーザー定義の注釈を使って権限ブロックを実現する例を紹介します。
Handler Interceptor(プロセッサブロック)
よくある使用シーン
  • ログログ:情報モニタリング、情報統計、PVなど
  • を計算するために、要求情報のログを記録する。
  • 性能モニタ:
  • 権限検査:
  • 共通行為:
  • カスタムコメントを使用して権限ブロックを実現します。
    まずHandlerInterceptor了解
    HandlerInterceptorには三つの方法があります。
    
    public interface HandlerInterceptor {
    
      //            
      boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)throws Exception;
    
      //           
      void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;
    
      //            
      void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;
    
    }
    
    上記のコメントには実行手順が明記されていますが、テストとテストの結果は以下の通りです。
    
    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
    afterCompration
    スクリーンショットの設定はどうすればいいですか?
    このブロックは何ですか?
    方法ブロックHandler Intercepter
    SpringMVCを使って、SpringMVCは方法による要求処理であることを知っています。Struts 2とは明らかに違います。そして、Controllerはシングルモードです。すべての要求はDispactch Servletからurl対応を要求する方法を呼び出します。それは方法ブロックです。どうやって分かりますか?
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      System.out.println(handler.getClass());
      return true;
    }
    実行結果:
    class org.springframe ewark.web.method.HandlerMethod
    スクリーンセーバーがどのように動作しているかを見ました。そして、方法レベルのスクリーンセーバーであることを知っています。その後、スクリーンセーバーをどのように設定するかを見てみてください。サーバーが動作している間に機能します。
    Handler Interceptorを実現
    HandlerInterceptorインターフェースを実現したり、Handler InterceptorAdapterクラスを継承したりします。
    Handler InterceptorAdapterアダプタは、Handler Intercepterインターフェースに対してデフォルトで実現されています。このようなアダプターモードは、開発者が復唱方法を求めるだけでなく、他の方法に対してもデフォルトで実施されています。
    上のTestInterceptorはDemoです。具体的には必要に応じてブロックしたい位置で論理処理ができます。
    スクリーンショットの設定
    Spring 4 xから、注釈構成をサポートします。具体的には@Configration注釈を使って、普通のクラスを表示します。このクラスを構成クラスにします。このクラスでBenを定義したり、配置パラメータを注入したりすることができます。
    まず、ブロックを配置するには、SpringMvcのブロックチェーンから私たちに注入されたブロックを取り込む必要があります。このようにして、中に入る時にブロックを要請します。私たちはブロックしたいという要求があります。ですから、普通のクラスを新たに作って、@Configrationの注釈を使ってクラス名に表示して、WebMvConfigfirer Adapterを引き継ぎます。方法が多すぎて、その中のすべての方法を複写する必要がないです。
    ここでは、私たちのスクリーンショットを設定するための設定クラスを新たに作成します。
    
    @Configuration
    public class InterceptorConfig extends WebMvcConfigurerAdapter {
    
      public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**");
      }
    }
    
    
    addInterceptorsを復唱した後、サーバーが起動したら、自動的にこの方法を呼び起こします。パラメータはどうやって送っても構いません。(今はjava初級段階です。Spring深層原理を研究する暇がありません。)この方法を知ったら、必ず呼び出されます。
    私達は直接newのカスタムブロックをブロックチェーン全体に登録し、ブロックパスを制定します。このように要求urlブロック構成を満足させると、私達のカスタムスクリーンセーバーが対応する方法を実行します。
    ブロッキング方法は非常に賢いです。ブロッキング構成の他に不整合もブロックできます。正規表現によるブロック要求もできます。
    これで、私達のスクリーンセーバーは完成しました。次はユーザー定義の権限に関するコメントです。
    カスタム権限のコメント
    一つ@interfaceクラスを定義します。
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Access {
    
      String[] value() default {};
    
      String[] authorities() default {};
    
      String[] roles() default {};
    
    }
    
    
    @Targetコメントはこの類を表示して表示できる場所です。
    一般的な要素タイプ(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 */
      //         
      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
    }
    
    @Retensionコメントは、本注釈(この注釈の注釈保持時期を表示する)を表しています。
    
    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.
       */
      //      ,     
      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
    }
    
    @Dcumentedドキュメントの表示を生成するかどうか、すなわちインターフェースドキュメントを生成するかどうかは、注釈ドキュメントを生成するかどうかです。
    注釈が完了しました。次は対応するcontrollerの方法に注釈を追加し、この方法が許可する権限を設定する必要があります。
    メソッドにパーミッションを設定します。
    
    @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";
      }
    }
    
    
    書き込み権限論理
    
    //           ,   HandlerInterceptorAdapter 
    public class AuthenticationInterceptor extends HandlerInterceptorAdapter {
    
      //            
      @Override
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //  handler   HandlerMethod,         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);
          }
          //                 ,                  Id
          //                    ,  set                
          String role = request.getParameter("role");
          if (StringUtils.isNotBlank(role)) {
            if (authSet.contains(role)) {
            //       true,       
              return true;
            }
          }
        }
        //             ,       
        return false;
      }
    
    }
    
    
    これでサーバーを起動し、インターフェースにアクセスすれば、効果が見られます。ここでは模範を示しません。
    以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。