- サーバーに重要な情報を保管し、接続を維持する方法である。
- 前のCookieの解決を解決するためには、重要な情報はすべてサーバに保存し、クライアントとサーバは Session ID(推定不可能な任意の識別子値、UUID 等使用) にて接続しなければならない。 この方法をSessionという。
@PostMapping("/login")
public String login(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletResponse response) {
if (bindingResult.hasErrors()) {
return "login/loginForm";
}
// 1. ユーザーがログイン情報(Login Form)を伝達すれば、サーバーで該当ユーザーであるか確認する。
Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
if (loginMember == null) {
bindingResult.reject("loginFail", "Dまたはパスワードが正しくありません。");
return "login/loginForm";
}
sessionManager.createSession(loginMember, response);
return "redirect:/";
}
@Component
public class SessionManager {
public static final String SESSION_COOKIE_NAME = "mySessionId";
// String : sessionId , Object : 値
private Map<String, Object> sessionStore = new ConcurrentHashMap<>();
// Session 生成
public void createSesssion(Object value, HttpServletResponse response) {
// 2.ユーザが正しければ、UUIDで推定できないsessionIdを作る。
String sessionId = UUID.randomUUID().toString();
// 3. sessionStoreを作り
// セッションIDと値(login Member)を保存する。
sessionStore.put(sessionId, value);
// 4. サーバはsessionIdのみをCookeに入れてクライアントに渡す。
Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId);
response.addCookie(mySessionCookie);
}
}
5.クライアントはCookieストレージにCookieを保管し、要求のたびにsessionIdを配信する。
- クライアントとサーバは結Cookieを介して接続するが、推定不可能なsessionIdのみを入れて配信し、会員情報のような重要な情報は配信しない。
6.その後、サーバーはクライアントが伝達したsessionIdでsessionStoreに保管しておいたSession情報を照会する。
- 長所
- sessionIdがハッキングされても、ここには重要な情報がない。
- sessionの満了時間を短く(ex。30分)設定すれば、sessionIdを盗んでも時間が経てば使用できなくなり、ハッキングが疑われる場合、サーバーから該当Session強制的に除去すれば良い。
@GetMapping("/")
public String homeLogin(HttpServletRequest request, Model model) {
// クライアントが伝達したsessionIdで
// sessionStoreに保管しておいたSession情報を照会する。
Member member = (Member)sessionManager.getSession(request);
//로그인
if (member == null) {
return "home";
}
model.addAttribute("member", member);
return "loginHome";
}
@Component
public class SessionManager {
// Sesssion 照会
public Object getSession(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies == null) {
return null;
}
for (Cookie cookie : cookies) {
if (cookie.getName().equals(SESSION_COOKIE_NAME)) {
return sessionStore.get(cookie.getValue());
}
}
return null;
}
}
7.ログアウトするときは、sessionStoreにある値を削除すればよいが、Servletが提供するHttpSession(以後、別途ポスト作成)を使用すれば、invalidateメソッドを使用すればよい。
@PostMapping("/logout")
public String logout(HttpServletRequest request) {
sessionManager.expire(request);
return "redirect:/";
}
@Component
public class SessionManager {
// Session 満了
public void expire(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(SESSION_COOKIE_NAME)) {
sessionStore.remove(cookie.getValue());
}
}
}
}
}