teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

追記

2020/06/17 14:16

投稿

rubytomato
rubytomato

スコア1752

answer CHANGED
@@ -192,4 +192,93 @@
192
192
  .sessionRegistry(sessionRegistry())
193
193
  ```
194
194
 
195
- ![イメージ説明](2b191801f3e0c206e4b7ebf96e1db8d4.gif)
195
+ ![イメージ説明](2b191801f3e0c206e4b7ebf96e1db8d4.gif)
196
+
197
+ **追記**
198
+
199
+ Spring Frameworkのプロジェクトの中で特に理解するのが難しいのがSpring Securityです。
200
+ 私もわからないことだらけなので詳しく説明できない部分もありますがご了承ください。
201
+
202
+
203
+ > 原因はsuperクラスのequalsとhashCodeメソッドを使用できていなかったことでしょうか?
204
+ > もしそうであるならば、
205
+
206
+ lombokの`@Data`アノテーションを付与するとアクセサメソッドが追加され、さらに`hashCode`、`equals`、`toString`メソッドがオーバーライドされます。
207
+ この`hashCode`、`equals`メソッドが不適切なコードでオーバーライドされるために期待する動作にならなかったという理解です。
208
+
209
+ > 元々、@EqualsAndHashCode(callSuper = true)と書いていたので、
210
+ > super classのequalsとhashCodeメソッドを利用していると思っていたのですが、
211
+ > 私の理解が違うのでしょうか。
212
+
213
+ `@EqualsAndHashCode(callSuper = true)`も`equals`、`toString`メソッドがオーバーライドされますが、スーパークラスのメソッドを利用する(呼ぶ)という動きではないようです。
214
+
215
+ > sessionRegistry(sessionRegistry())がないと、
216
+ > ログアウト後もセッションが残り続け、再ログインができなくなると教えて頂きましたが、
217
+ > ここが良く分かりませんでした。
218
+
219
+ 挙動を確認するのが一番だと思いますので、ソースコードを以下のように修正して試してみてください。
220
+ セキュリティコンフィグレーションのセッション制御の部分と追加したメソッドをコメントアウトします。
221
+
222
+ ```java
223
+ .sessionManagement()
224
+ .maximumSessions(1)
225
+ .maxSessionsPreventsLogin(true)
226
+ // .sessionRegistry(sessionRegistry())
227
+ ```
228
+
229
+ ```java
230
+ /*
231
+ // Work around https://jira.spring.io/browse/SEC-2855
232
+ @Bean
233
+ public SessionRegistry sessionRegistry() {
234
+ SessionRegistry sessionRegistry = new SessionRegistryImpl();
235
+ return sessionRegistry;
236
+ }
237
+
238
+ // Register HttpSessionEventPublisher
239
+ @Bean
240
+ public static ServletListenerRegistrationBean httpSessionEventPublisher() {
241
+ return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
242
+ }
243
+ */
244
+
245
+ ```
246
+
247
+ 修正が終わったらアプリケーションを起動し、ログイン → ログアウト → ログインを行ってみてください。
248
+ 2度目のログインができないと思います。(ブラウザを立ち上げなおしてもログインできません)
249
+ これはサーバー側でセッションが有効なままだということだと思います。
250
+
251
+ この挙動を回避するために上記でコメントアウトした部分が必要になります。
252
+
253
+
254
+ > 紹介して頂いたページを参照して、sessionRegistryがBeanとして公開されないので、
255
+ > 上記のコーディングをしているのはなんとなく理解できたのですが、
256
+ > sessionRegistryを公開しないとログアウト時にセッションを破棄出来ないのでしょうか。
257
+
258
+ > springは特別な実装をしなくても、ログアウト時にセッションを破棄する仕様だと思うのですが、
259
+ > 多重ログインを禁止しているとこの仕様が無効になってしまうのでしょうか。
260
+
261
+ このあたりの挙動は私自身もよくわかりません。
262
+ ちなみにログアウト時にセッションを破棄する処理はセキュリティコンフィグレーションの以下の部分で行いますが、
263
+ この部分だけあっても上記の2度目のログインはできません。
264
+
265
+ ```java
266
+ .logout()
267
+ .logoutSuccessUrl("/index")
268
+ .deleteCookies("JSESSIONID")
269
+ .invalidateHttpSession(true)
270
+ ```
271
+
272
+
273
+ > rubytomato様のgithubにあるセキュリティコンフィグレーションの最後に、
274
+ > httpSessionEventPublisher()メソッドを定義していると思いますが、
275
+ > これは具体的に何をする処理なのでしょうか。
276
+
277
+ こちらもよくわかりません。
278
+ コード自体は[Spring Security logout and Maximum sessions](https://stackoverflow.com/questions/41429778/spring-security-logout-and-maximum-sessions)を参考しました。
279
+ `sessionRegistry()`と`httpSessionEventPublisher()`の両方で機能するらしく、どちらか欠けても期待する動作にはなりません。
280
+
281
+
282
+ 私が答えられるのは以上になりますが、おそらくこれでは納得できない部分もあると思います。
283
+ その場合は改めて質問を立ててください。より詳しい回答者からもっとよい回答が得られると思います。
284
+ 一番いいのはstackoverflow(英語版の方)で質問することです。もしかするとSpring Securityの開発者の方から回答が貰えるかもしれません。