[MVC2] 7. ログイン処理2-フィルタ、インタフェース


[前の位置]


HttpSessionを使用してクライアントのセッション、sessionを作成します.setAttributeでユーザーをセッションに保存します.その後、HomeControllerはユーザーを@SessionAttributeに連れて行き、ログインユーザーに異なるビューを提供することができます.ただし登録されていないユーザは、登録されている人だけがアクセスできる商品管理などのページにURLでアクセスすることもできます.商品管理など全ページにログイン確認ロジックを追加できますが、これは非常に面倒です.これらのWebに関する共通の関心事項処理にはフィルタやインタフェースが用いられる.
セッションでログインを保持できます.ただしログインしている人だけがアクセスできるように制御することはできません.これはフィルタまたはインターセプタで処理されます.

[補助フィルタ]


フィルタバー


HTTPリクエスト->WAS->フィルタ->ディスパッチ->コントローラ
フィルタはサーブレットでサポートされているシャッターです.フィルタはbritを呼び出す前に呼び出されます.フィルタチェーンを使用して複数のフィルタを呼び出すこともできます.また、サーバの呼び出しを回避するために中断することもできます.

フィルタの使用


フィルタを使用するには、Filterインタフェースを実装し、FilterRegistrationBeanに登録します.
public class LoginCheckFilter implements Filter {

    private static final String[] whitelist = {"/", "/members/add", "/login", "/logout", "/css/*"};

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String requestURI = httpRequest.getRequestURI();

        HttpServletResponse httpResponse = (HttpServletResponse) response;

        try {
            log.info("인증 체크 필터 시작 {}", requestURI);

            if (isLoginCheckPath(requestURI)) {
                log.info("인증 체크 로직 실행 {}", requestURI);
                HttpSession session = httpRequest.getSession(false);
                if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {

                    log.info("미인증 사용자 요청 {}", requestURI);
                    //로그인으로 redirect
                    httpResponse.sendRedirect("/login?redirectURL=" + requestURI);
                    return;
                }
            }

            chain.doFilter(request, response);
        } catch (Exception e) {
            throw e; //예외 로깅 가능 하지만, 톰캣까지 예외를 보내주어야 함
        } finally {
            log.info("인증 체크 필터 종료 {} ", requestURI);
        }

    }

    /**
     * 화이트 리스트의 경우 인증 체크X
     */
    private boolean isLoginCheckPath(String requestURI) {
        return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
    }
}
上はログインフィルタの実装です.doFilterはセッションをサーブレットRequestとサーブレットResponseオブジェクトとして検証し、成功した場合はチェーンします.dofilterを使用して次のフィルタ/サーバを呼び出します.
@Bean
public FilterRegistrationBean loginCheckFilter() {
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new LoginCheckFilter());
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.addUrlPatterns("/*");

        return filterRegistrationBean;
    }
次にコンフィギュレーションクラスを作成し、FilterRegistrationBeanを空に登録します.ここでsetFilterを使用してフィルタを追加すればよい.

[ばね継手]


Spring intercepterは、springフィルタなどのWebページに関連する共通の関心のある問題を効果的に解決することもできます.AOPは処理することもできるが、Webに関連する注目点は、要求、応答オブジェクトが利用可能なフィルタまたはインタフェースを使用する.

こうさ


HTTPリクエスト->WAS->フィルタ->ディスパッチ->インタフェース->コントローラ

まず,インタフェースはDispatcherであり,その後コントローラ呼び出しの前に呼び出される.1つの方法しか使用しないdofilterフィルタとは異なり、intercepterは3つの方法をカバーすることができる.
  • preHandle:コントローラ呼び出しの前に呼び出されます.
  • PostHandle:コントローラがModelAndViewを返して呼び出す.コントローラに異常が発生した場合は呼び出されません.
  • afterCompletion:レンダリングビューの後に呼び出されます.異常が発生しても呼び出されます.
    IntercepterはスプリングMVC構造特化フィルタの機能を提供しているので、特別な場合を除きスプリングにIntercepterを使用する.
  • インタフェースの使用


    インタフェースは、Handler Interceptorインタフェースを上書きすることによって作成されます.
    WebMvcConfiguratorでaddInterceptrosを上書きし、インタフェースを登録すればよい.
    インタフェースの作成
    public class LoginCheckInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            String requestURI = request.getRequestURI();
    
            log.info("인증 체크 인터셉터 실행 {}", requestURI);
    
            HttpSession session = request.getSession();
    
            if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
                log.info("미인증 사용자 요청");
                //로그인으로 redirect
                response.sendRedirect("/login?redirectURL=" + requestURI);
                return false;
            }
    
            return true;
        }
    }
    インタフェース登録
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
    
            registry.addInterceptor(new LoginCheckInterceptor())
                    .order(1)
                    .addPathPatterns("/**")
                    .excludePathPatterns("/", "/members/add", "/login", "/logout",
                            "/css/**", "/*.ico", "/error");
        }
    ログインはコントローラ呼び出し前に完了し、preHandleを上書きするだけです.Intercepterは、登録時にexcludePathPatternsとして除外するURLを追加できるので、whitelistをintercepterの内部に置く必要はありません.

    [フィルタvsセパレータ]


    フィルタ

  • タブレットが提供する機能
  • Filterインタフェースを実装
  • を作成する.
  • ディスパッチは、ブレードの前に
  • を呼び出す.
  • 度Filterメソッドのみがオーバーシュート
  • をサポート
  • FilterRegistration beanを空に追加し、内部に
  • を登録します.
  • ExcludePatternsは提供する、フィルタ内部処理
  • が必要である.

    受信者

  • スプリングが提供する機能
  • Handler Interceptorインタフェースを実装
  • を作成する.
  • ディスパッチプログラムは、ブレードの後に
  • を呼び出す.
  • は、3つの方法の移行をサポートします.
    -preHandle:コントローラが呼び出される前に
  • 後Handle:コントローラに戻った後
  • afterCompletion:レンダリングビュー後
  • 実装
  • WebMvcConfiguratorのクラスでaddInterceptorsを上書きし、内部登録
  • excludePatternsを提供し、特定のUrl上で実行するように柔軟に設定できます.