質問編集履歴

3

ユーザ名とパスワードを追記

2020/06/16 21:42

投稿

waito
waito

スコア23

test CHANGED
File without changes
test CHANGED
@@ -384,6 +384,8 @@
384
384
 
385
385
  必要であればご確認をお願い致します。
386
386
 
387
+ ウェブアプリのユーザ名とパスワードはそれぞれuser1とdemoです。
388
+
387
389
 
388
390
 
389
391
  [https://github.com/uekiGityuto/test-session-control](https://github.com/uekiGityuto/test-session-control)

2

不要な処理のコメントアウト

2020/06/16 21:42

投稿

waito
waito

スコア23

test CHANGED
File without changes
test CHANGED
@@ -154,7 +154,7 @@
154
154
 
155
155
  多重ログインチェックを機能させるためには、UserDetailsを実装したクラスの中で、
156
156
 
157
- equalsとhashCodeメソッドのオーバーライドを適切に行う必要らしく、
157
+ equalsとhashCodeメソッドのオーバーライドを適切に行うことが必要らしく、
158
158
 
159
159
  それが出来ていないのではないかと考えています。
160
160
 
@@ -318,20 +318,18 @@
318
318
 
319
319
 
320
320
 
321
- public User getUser() {
322
-
323
- return user;
324
-
325
- }
326
-
327
-
328
-
329
- /*
330
-
331
- * lombokを使わずに実装してみた
321
+ /* lombokを使わずに実装してみた
332
322
 
333
323
  *
334
324
 
325
+ * public User getUser() {
326
+
327
+ * return user;
328
+
329
+ * }
330
+
331
+ *
332
+
335
333
  * @Override
336
334
 
337
335
  * public int hashCode() {

1

原因を絞り込めましたので追記しました。

2020/06/16 18:05

投稿

waito
waito

スコア23

test CHANGED
File without changes
test CHANGED
@@ -128,9 +128,275 @@
128
128
 
129
129
 
130
130
 
131
+ ## 追記
132
+
133
+ 問題のプロジェクトとは別に、
134
+
135
+ 多重ログイン禁止処理を確かめるためのプロジェクトを新規に作成して試してみました。
136
+
137
+
138
+
139
+ すると、WebSecurityConfigurerAdapterを継承したクラスに、
140
+
141
+ 上記と同様、最大セッション数を1とするコードを書くと2重ログインを禁止出来ました。
142
+
143
+
144
+
145
+ そこから少しずつ、問題のプロジェクトに近づけていくと、
146
+
147
+ ログインに使用しているUSERテーブルのNAMEカラムを外部キーにもつMUTTERテーブルを作成し、
148
+
149
+ USERテーブルと関連性をもたせたタイミングで2重ログインが禁止できなくなりました。
150
+
151
+
152
+
153
+ ここからは予想なのですが、[この記事](https://qiita.com/rubytomato@github/items/a9a19f4a1cd5d732e5f8)によると、
154
+
155
+ 多重ログインチェックを機能させるためには、UserDetailsを実装したクラスの中で、
156
+
157
+ equalsとhashCodeメソッドのオーバーライドを適切に行う必要らしく、
158
+
159
+ それが出来ていないのではないかと考えています。
160
+
161
+
162
+
163
+ その観点から考えたのですが、結局何が問題か分からず、アドバイスをお願い致します。
164
+
165
+ なお、DB操作にはJPAを利用しています。
166
+
167
+
168
+
169
+ [Userエンティティクラス]
170
+
171
+ ```Java
172
+
173
+ package sample.spring.domain;
174
+
175
+
176
+
177
+ import java.io.Serializable;
178
+
179
+ import java.util.List;
180
+
181
+
182
+
183
+ import javax.persistence.CascadeType;
184
+
185
+ import javax.persistence.Column;
186
+
187
+ import javax.persistence.Entity;
188
+
189
+ import javax.persistence.FetchType;
190
+
191
+ import javax.persistence.GeneratedValue;
192
+
193
+ import javax.persistence.GenerationType;
194
+
195
+ import javax.persistence.Id;
196
+
197
+ import javax.persistence.OneToMany;
198
+
199
+ import javax.persistence.Table;
200
+
201
+
202
+
203
+ import com.fasterxml.jackson.annotation.JsonIgnore;
204
+
205
+
206
+
207
+ import lombok.AllArgsConstructor;
208
+
209
+ import lombok.Data;
210
+
211
+ import lombok.NoArgsConstructor;
212
+
213
+ import lombok.ToString;
214
+
215
+
216
+
217
+ @Entity
218
+
219
+ @Table(name = "USER")
220
+
221
+ @Data
222
+
223
+ @NoArgsConstructor
224
+
225
+ @AllArgsConstructor
226
+
227
+ @ToString(exclude = "mutters")
228
+
229
+ public class User implements Serializable {
230
+
231
+ private static final long serialVersionUID = 1L;
232
+
233
+
234
+
235
+ @Id
236
+
237
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
238
+
239
+ @Column(name = "USER_ID")
240
+
241
+ private Integer Id;
242
+
243
+
244
+
245
+ @Column(unique = true, nullable = false, name = "NAME", length = 64)
246
+
247
+ private String name;
248
+
249
+
250
+
251
+ @Column(nullable = false, name = "PASS", length = 80)
252
+
253
+ @JsonIgnore
254
+
255
+ private String pass;
256
+
257
+
258
+
259
+ // 以下をコメントアウトすると2重ログインが禁止出来る
260
+
261
+ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
262
+
263
+ private List<Mutter> mutters;
264
+
265
+
266
+
267
+ }
268
+
269
+ ```
270
+
271
+
272
+
273
+ [UserDetailsを実装したUserクラスを継承したクラス]
274
+
275
+ ```Java
276
+
277
+ package sample.spring.service;
278
+
279
+
280
+
281
+ import java.util.Collection;
282
+
283
+
284
+
285
+ import org.springframework.security.core.GrantedAuthority;
286
+
287
+
288
+
289
+ import sample.spring.domain.User;
290
+
291
+
292
+
293
+ import lombok.Data;
294
+
295
+ import lombok.EqualsAndHashCode;
296
+
297
+
298
+
299
+ @Data
300
+
301
+ @EqualsAndHashCode(callSuper = true)
302
+
303
+ public class LoginUserDetails extends org.springframework.security.core.userdetails.User {
304
+
305
+ private static final long serialVersionUID = 1L;
306
+
307
+ private final User user;
308
+
309
+
310
+
311
+ public LoginUserDetails(User user, Collection<GrantedAuthority> authorities) {
312
+
313
+ super(user.getName(), user.getPass(), authorities);
314
+
315
+ this.user = user;
316
+
317
+ }
318
+
319
+
320
+
321
+ public User getUser() {
322
+
323
+ return user;
324
+
325
+ }
326
+
327
+
328
+
329
+ /*
330
+
331
+ * lombokを使わずに実装してみた
332
+
333
+ *
334
+
335
+ * @Override
336
+
337
+ * public int hashCode() {
338
+
339
+ * return user.getName().hashCode();
340
+
341
+ * }
342
+
343
+ *
344
+
345
+ * @Override
346
+
347
+ * public boolean equals(Object rhs) {
348
+
349
+ * if (rhs instanceof User) {
350
+
351
+ * return user.getName().equals(((LoginUserDetails) rhs).user.getName()); }
352
+
353
+ * return false;
354
+
355
+ * }
356
+
357
+ *
358
+
359
+ * @Override
360
+
361
+ * public String toString(){
362
+
363
+ * StringBuilder sb = new StringBuilder();
364
+
365
+ * sb.append("Username: ").append(this.user.getName()).append("; ");
366
+
367
+ * sb.append("Password: [PROTECTED]; ");
368
+
369
+ *
370
+
371
+ * return sb.toString();
372
+
373
+ * }
374
+
375
+ */
376
+
377
+
378
+
379
+ }
380
+
381
+ ```
382
+
383
+
384
+
385
+ その他のクラスはGitHubにソースを配置したので、
386
+
387
+ 必要であればご確認をお願い致します。
388
+
389
+
390
+
391
+ [https://github.com/uekiGityuto/test-session-control](https://github.com/uekiGityuto/test-session-control)
392
+
393
+
394
+
395
+
396
+
131
397
  ## 補足
132
398
 
133
- 上記で省略していたSecurityConfigの全量を書きます。
399
+ 上記で省略していた問題のあるプロジェクトで使用しているSecurityConfigの全量す。
134
400
 
135
401
 
136
402