HttpSession

- Servletが公式支援するSessionで、一定時間使用しなければ該当Sessionを削除する機能などを提供する。
    ```java
    @PostMapping("/login")
    public String login(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult,
                          HttpServletRequest request) {
        if (bindingResult.hasErrors()) {
            return "login/loginForm";
        }
    
        Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
    
        if (loginMember == null) {
            bindingResult.reject("loginFail", "IDまたはパスワードが正しくありません。");
            return "login/loginForm";
        }
    
        //ログイン成功処理
        //Sessionがあればあるセッションを返却、なければ新規Sessionを作成
        HttpSession session = request.getSession();
        //Sessionにログイン情報を保存
        session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
    
        return "redirect:/";
    
    }
    
    @PostMapping("/logout")
    public String logout(HttpServletRequest request) {
        //Sessionがなければnullを返却
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();
        }
        return "redirect:/";
    }
    ```
    ```java
    @GetMapping("/")
    // public String homeLogin(HttpServletRequest request, Model model) {
    
    //    HttpSession session = request.getSession(false);
    //    if (session == null) {
    //        return "home";
    //    }
    //		Member loginMember = (Member)session.getAttribute(SessionConst.LOGIN_MEMBER);
    
    public String homeLogin(
                @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember, Model model) {
    
        // Session会員データがなければhomeに遷移
        if (loginMember == null) {
            return "home";
        }
    
        // Sessionが維持されるとloginHomeに遷移
        model.addAttribute("member", loginMember);
        return "loginHome";
    }
    ```

- セッションにはidや会員名程度最小限のデータだけを保存しなければならない。
    保存したデータ用廊*ユーザー数でSessionのメモリ使用量が急激に増え、障害につながりかねないためだ。

- ログインを初めて試みると、以下のようにURLがjsessionidを含んでいる。 
    サーバーの立場ではウェブブラウザがCookieをサポートしているかどうか最初は分からないため、ウェブブラウザがCookieをサポートしていない時はCookieの代わりにURLを通じてSessionを維持する。
    ![스크린샷 2023-10-28 16.32.09 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567846/ffec8080-06ef-f6a3-5034-066ec7753a37.png)

- ちなみに、Thymeleafのようなテンプレートエンジンを使えば、jsessionidをURLに自動的に含めてくれる。
- URL配信方式をオフにし、常にCookieを通じてSessionを維持したい場合は、次のオプションを入れるとjsessionidが露出されない。
    > application.properties
    > server.servlet.session.tracking-modes=cookie
- その他にもSessionを通じて以下のものなどを確認することができる。
    ```java
    @GetMapping("/session-info")
    public String sessionInfo(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null) {
            return "세션이 없습니다.";
        }
    
        //Sessionデータ出力
        session.getAttributeNames().asIterator()
                .forEachRemaining(name -> log.info("session name={}, value={}", name, session.getAttribute(name)));
    
        log.info("sessionId={}", session.getId());
    		// 無効化させる最大Interval(秒)、last Accessed Timeを基準とする。
        log.info("getMaxInactiveInterval={}", session.getMaxInactiveInterval());
        log.info("creationTime={}", new Date(session.getCreationTime()));
        log.info("lastAccessedTime={}", new Date(session.getLastAccessedTime()));
        log.info("isNew={}", session.isNew());
    
        return "세션 출력";
    
    }
    ```

- タイムアウト設定もできる。
    - sessionは、ユーザーがログアウトを直接呼び出して、session.invalidate()が呼び出される場合に削除される。
    しかし、ほとんどのユーザーはログアウトを選択しないで、ただウェブブラウザーを終了する。
    HTTPは雨連結性(ConnectionLess)とサーバーの立場ではこれを知らない。
    このようにsessionデータを削除できず、無制限に保管することになると、問題が発生することができる。
    - 解決策 : 最近に要請した時間を基準にapplication.propertiesを通じてグローバルに時間制限を設定し、特定Session単位で時間を設定しなければならない場合Javaコードで設定する。
    ```
    server.servlet.session.timeout=1800//30分
    ```