Spring SecurityおよびOAuth 2.0を使用したログイン機能(04-05)

6565 ワード

04.声明に基づいて改善する


セッション値の入力時に同じコードが繰り返される場合を改善します.
SessionUser user = (SessionUser) httpSession.getAttribute("user");
  • インデックスメソッドに加えて、他のコントローラおよびメソッドがセッション値を必要とする場合は、
  • をセッションから直接インポートする必要があります.
  • のようなコードの重複は不要なので、このセクションをメソッドパラメータを使用してセッション値
  • を直接取得するように変更できます.

    4-1) config.authパッケージに@LoginUser宣言を作成する

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.PARAMETER) // 1.
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LoginUser { // 2.
    }
  • @Target(ElementType.PARAMETER)
  • 、次いで、ノイズを生成することができる位置
  • を調整する.
  • PARAMETERが指定されており、メソッドパラメータとして宣言されたオブジェクトに対してのみ
  • を使用できます.
  • のほか、クラス宣言に使えるTYPEなどがあります.
  • @interface
  • このファイルをアシスタントクラス
  • として指定する
  • LoginUserというプレゼンテーションが作成されました.
  • 4-2)同じ場所にLoginUserArcgumentResolverを作成する

  • LoginUserArcgumentResolverというHandlerMethodArcgumentResolverインタフェースのクラス
  • を実装する
  • Handler MethodArcgumentResolverは1つの機能をサポートする
    :メソッドが条件を満たす場合、HandlerMethodArcgumentResolverのインプリメンテーションとして指定する値をメソッドのパラメータ
  • に渡すことができる.
    import lombok.RequiredArgsConstructor;
    import org.springframework.core.MethodParameter;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.support.WebDataBinderFactory;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    import javax.servlet.http.HttpSession;
    
    @RequiredArgsConstructor
    @Component
    public class LoginUserArgumentResolver
            implements HandlerMethodArgumentResolver {
        private final HttpSession httpSession;
    
        @Override
        public boolean supportsParameter(MethodParameter parameter){ // 1.
            boolean isLoginUserAnnotation
                    = parameter.getParameterAnnotation(LoginUser.class) != null;
            boolean isUserClass = SessionUser.class.equals(parameter.getParameterType());
            return isLoginUserAnnotation && isUserClass;
        }
    
        @Override // 2.
        public Object resolveArgument(MethodParameter parameter,
                                     ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
                                     WebDataBinderFactory binderFactory) throws Exception{
            return httpSession.getAttribute("user");
        }
    }
  • supportsParameter()
  • コントローラメソッドが特定のパラメータ
  • をサポートするかどうかを決定する.
  • では、パラメータに@LoginUser宣言があります.
    パラメータクラスタイプはSessionUserです.クラスはtrue
  • を返します
  • resolveArgument
  • パラメータに渡すオブジェクト
  • を作成します.
  • セッションからオブジェクト
  • をインポートする.

    4-3)構成パッケージにWebConfigクラスを作成する

  • LoginUserArgumentResolverは、Springで識別するためにWebMvcConfiguratorに追加されました.
  • Handler MethodArgumentResolverは常にWebMvcConfiguratorのaddArgumentResolver()で追加する必要があります.
  • 他のHandler MethodArcgumentResolverが必要な場合は、同様に追加できます.
    import lombok.RequiredArgsConstructor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    import java.util.List;
    
    @RequiredArgsConstructor
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        private final LoginUserArgumentResolver loginUserArgumentResolver;
    
        @Override
        public void addArgumentResolvers(
                List<HandlerMethodArgumentResolver> argumentResolvers){
            argumentResolvers.add(loginUserArgumentResolver);
        }
    }

    4-4)IndexControllerコードのすべての重複部分を@LoginUserに改良

    ...
    public class IndexController {
    
        private final PostsService postsService;
        //private final HttpSession httpSession;
    
        @GetMapping("/")
        public String index(Model model, @LoginUser SessionUser user){ // 1.  4.
            model.addAttribute("posts", postsService.findAllDesc());
            //SessionUser user = (SessionUser) httpSession.getAttribute("user"); // 2.
            if(user != null){ // 3.
                model.addAttribute("user", user.getName());
            }
            return "index";
        }
       ...
  • @LoginUser SessionUser user
  • 既存のユーザhttpSession.getAttribute(「user」)にインポートするセッション情報値
  • が改善されました.
  • 現在、どのコントローラも@LoginUserでセッション情報
  • を取得できるようになりました.

    4-5)ログインが正常に動作していることを確認する



    05.セッション・リポジトリとしてデータベースを使用する


  • 現在のサービスでは、セッションが埋め込まれたTomcatのメモリに格納されているため、アプリケーションの再実行はログインを無効にします.

  • デフォルトでは、セッションはWASを実行するメモリに格納され、呼び出されます.したがって、アプリケーションを実行するときの構造では、埋め込み型Tomcatなどのセッションは常に初期化されます.
    =>導入のたびにTomcatが再起動されます.

  • また、複数のサーバが実行されている場合は、Tomcatごとにセッション同期を設定する必要があります.したがって、実際の「現状」では、セッションストレージには次の3つの選択肢が選択されています.
  • 猫セッションを使用
  • のデフォルトは
  • で、通常は設定されていません.
  • の場合、セッションは「猫」(WAS)に格納されるので、2つ以上のWAS駆動環境では、「猫」間でセッションの追加設定
  • を共有する必要がある.
  • MySQLなどのデータベースをセッション・リポジトリとして使用
  • 複数のWAS間でセッションを共有する最も簡単な方法
  • は、多くの設定を必要としないが、最終的にはログイン要求ごとにDB IOが生成するため、パフォーマンスに問題が発生する
  • .
  • は、通常、内部システム
  • のために、ログイン要求の多いバックグラウンドオフィスを必要としない.
    メモリDB(例えば
  • RedisおよびMemcached)をセッションストレージとして使用する
  • B 2 Cサービスで最も一般的な方法は
  • です.
  • 実際のサービスでは、Embedded Redisではなく外部メモリサーバが必要です.
  • データベースをセッションとして格納する第2の方法を選択します.これは、設定が容易で、ユーザーが多くなく、コストが低いサービスです.
    メモリDB(
  • Redisなど)は、
  • を別途支払う必要がある.

    5-1)spring-sessession-jdbcの登録


    1. build.gradleへの依存性の登録

    compile('org.springframework.session:spring-session-jdbc')

    2. application.propertiesでjdbcとしてセッション・リポジトリを選択

    spring.session.store-type=jdbc

    5-2)テスト登録


    アプリケーションテストログインを再実行し、h 2-consoleに接続
    SELECT * FROM SPRING_SESSION
  • セッションの2つのテーブル
  • が作成されていることがわかります.
  • JPAは自動的にセッションテーブルを作成し、何の操作も必要としない
  • .
  • H 2によるばねの再運転時にはH 2も再起動するので、現在では、以前のようにばねを再起動するとセッションは
  • 解放される.
  • 以降AWSに配備され、セッションは解除されません