ログインしないURL直アクセスの防止
業務アプリケーションではほとんどの場合、ログイン画面でユーザー認証を行い、メインメニューから各画面に遷移します。
ログインせずにURL直打ちで各画面が利用できてしまうと認証の意味がないので、 意図しないアクセスは事前にトラップして「ログインしていません」エラーページに遷移するか、 黙ってログイン画面に遷移するかを行うと思います。ここでは独自のエラーページに遷移する例で説明します。

[1] Interceptorクラスの作成
インターフェース HandlerInterceptor を実装するクラスを作成し、preHandleメソッドをオーバーライドします。
この処理で防止すべきアクセスを見つけたらエラーのURLに遷移してfalseを返します。
エラーURLはここでは /denied としていますが、自由に決められます。
一方、正当なアクセスとして要求を通過させたい場合はtrueを返すように作ります。

import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if(request.getSession().getAttribute("LoginUserId") == null) {
            // ログイン情報がない…エラーページに飛ぶ
            response.sendRedirect("denied");
            return false;  // アクセスされたControllerには到達させない意味
        }
        return true;  // 処理を許可
    }
}

[2] Interceptor登録処理クラスを作る
Interceptor が効くようにアプリケーションに登録する処理は、様々な実装例があるようですが、 WebMvcConfigurer インターフェースを実装した、慣習的に WebMvcConfig という名前のクラスを作ることが多いようです。
下記の例のように、チェックを適用するURLパターン、その中で除外するURLパターンを定義できます。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Bean
    public LoginCheckInterceptor LoginCheckInterceptor() {
        return new LoginCheckInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry
        .addInterceptor(LoginCheckInterceptor())
        .addPathPatterns("/STNP*") // チェック対象のURLパターン
        /*.excludePathPatterns("/index", "/login")*/ // 除外したいパターンをここに書く
        ;
    }
}

[3] エラーページの作成
先述の通り、エラーで弾いたら /denied というURLに遷移するInterceptorを作成したので、 それをハンドルするControllerクラスを作成します。

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import jakarta.servlet.http.HttpServletRequest;

@Controller
public class LoginErrorController implements ErrorController {
    @RequestMapping("/denied")
    @ResponseBody
    public String handleDenied(HttpServletRequest request) {
        final String s =
          "<html lang='ja'><body><h3>ログインしていません</h3>" +
          "以下のいずれかが原因に考えられます。解決しない場合システム管理者にご連絡ください。" +
          "<ul>" +
          "<li>メニューシステムにログインせずにアクセスされました。</li>" +
          "<li>前回画面操作から時間が経過したのでタイムアウトしました。</li>" +
          "</ul>" +
          "</body></html>";
        return s;
    }
}

Java kowaza Top

(first uploaded 2024/08/19 last updated 2024/08/19, URANO398)