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

質問編集履歴

2

UserDetailsServiceインターフェースの実装クラス、セキュリティコンフィグレーションクラスを追記しました。

2020/02/07 13:46

投稿

shinichi-ito
shinichi-ito

スコア9

title CHANGED
File without changes
body CHANGED
@@ -16,8 +16,9 @@
16
16
  該当コードを下記にまとめます。
17
17
 
18
18
  Entity
19
+
20
+
19
21
  ```ここに言語を入力
20
-
21
22
  @Entity
22
23
  @Table(name = "user")
23
24
  @Data
@@ -36,10 +37,12 @@
36
37
 
37
38
 
38
39
  }
40
+ ```
39
41
  UserDetailsインターフェースの実装コード
40
42
  このコード内で「LoginUser」からidを取得する独自メソッドを設定しています。
41
43
 
42
44
 
45
+
43
46
  ```ここに言語を入力
44
47
  public class UserDetailsImpl implements UserDetails {
45
48
 
@@ -103,6 +106,7 @@
103
106
 
104
107
  }
105
108
  ```
109
+
106
110
 
107
111
  controllerクラス内のメソッドに引数として「@AuthenticationPrincipal UserDetailsImpl userDetails」を設定しています。
108
112
  そして「System.out.println(userDetails.getUserId());」でユーザーidを取得しようとしていますがnullが返ってきます。

1

UserDetailsServiceインターフェースの実装クラス、セキュリティコンフィグレーションクラスを追記しました。

2020/02/07 13:46

投稿

shinichi-ito
shinichi-ito

スコア9

title CHANGED
File without changes
body CHANGED
@@ -17,20 +17,7 @@
17
17
 
18
18
  Entity
19
19
  ```ここに言語を入力
20
- package com.example.demo.entity;
21
20
 
22
- import javax.persistence.Column;
23
- import javax.persistence.Entity;
24
- import javax.persistence.Id;
25
- import javax.persistence.Table;
26
-
27
- import lombok.Data;
28
-
29
- /**
30
- * ログインユーザのユーザ名、パスワードを格納するためのEntity
31
- * @author aoi
32
- *
33
- */
34
21
  @Entity
35
22
  @Table(name = "user")
36
23
  @Data
@@ -49,22 +36,122 @@
49
36
 
50
37
 
51
38
  }
52
- ```
53
-
54
39
  UserDetailsインターフェースの実装コード
55
40
  このコード内で「LoginUser」からidを取得する独自メソッドを設定しています。
41
+
42
+
56
43
  ```ここに言語を入力
57
- package com.example.demo.model;
44
+ public class UserDetailsImpl implements UserDetails {
58
45
 
46
+ private static final long serialVersionUID = 1L;
59
- import java.util.Collection;
47
+ private LoginUser user;
60
48
 
61
- import org.springframework.security.core.GrantedAuthority;
62
- import org.springframework.security.core.userdetails.UserDetails;
49
+ protected UserDetailsImpl() {};
63
50
 
64
- import com.example.demo.entity.LoginUser;
51
+ public UserDetailsImpl(LoginUser user) {
52
+ this.user=user;
65
53
 
54
+ }
55
+
56
+ public int getUserId() {
57
+ return user.getUserId();
58
+ }
59
+
60
+
61
+ @Override
62
+ public Collection<? extends GrantedAuthority> getAuthorities() {
63
+ // TODO 自動生成されたメソッド・スタブ
64
+ return null;
65
+ }
66
+
67
+ @Override
68
+ public String getPassword() {
69
+ // TODO 自動生成されたメソッド・スタブ
70
+ return null;
71
+ }
72
+
73
+ @Override
74
+ public String getUsername() {
75
+ // TODO 自動生成されたメソッド・スタブ
76
+ return null;
77
+ }
78
+
79
+ @Override
80
+ public boolean isAccountNonExpired() {
81
+ // TODO 自動生成されたメソッド・スタブ
82
+ return false;
83
+ }
84
+
85
+ @Override
86
+ public boolean isAccountNonLocked() {
87
+ // TODO 自動生成されたメソッド・スタブ
88
+ return false;
89
+ }
90
+
91
+ @Override
92
+ public boolean isCredentialsNonExpired() {
93
+ // TODO 自動生成されたメソッド・スタブ
94
+ return false;
95
+ }
96
+
97
+ @Override
98
+ public boolean isEnabled() {
99
+ // TODO 自動生成されたメソッド・スタブ
100
+ return false;
101
+ }
102
+
103
+
104
+ }
105
+ ```
106
+
107
+ controllerクラス内のメソッドに引数として「@AuthenticationPrincipal UserDetailsImpl userDetails」を設定しています。
108
+ そして「System.out.println(userDetails.getUserId());」でユーザーidを取得しようとしていますがnullが返ってきます。
109
+ ```ここに言語を入力
110
+
111
+
112
+ @Controller
113
+ public class HomeController {
114
+
115
+ // インスタンスを作成しDIコンテナに格納。
116
+ @Autowired
117
+ UserService userService;
118
+
119
+ //userListのアドレスにアクセスした際にGetメソッドを実行。
120
+ @GetMapping("/userList")
121
+ public String getUserList(Model model,@AuthenticationPrincipal UserDetailsImpl userDetails) {
122
+
123
+
124
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
125
+ //Principalからログインユーザの情報を取得
126
+ String userName = auth.getName();//ユーザー名は取得できます。
127
+ System.out.println(userDetails.getUserId()); // userIdは nullが返ってきます。
128
+
129
+ //@Autowiredで作成したインスタンスを元に、userServiceのメソッドを呼び出す。
130
+ List<User> userList = userService.selectMany();
131
+ //userServiceから受け取ったデータをView側に渡す。
132
+ model.addAttribute("userList", userList);
133
+ model.addAttribute("userName", userName);
134
+
135
+ //template配下のファイル名を指定することでViewを呼び出せる。
136
+ return "userList";
137
+ }
138
+ }
139
+ ```
140
+ 何が原因かわからず詰まっております。
141
+ 何卒よろしくお願いいたします。
142
+
143
+
144
+
145
+
146
+ ------------------------------------------------------
147
+
148
+ **編集、追記依頼をいただきましたのでお言葉に甘えて追記しました。**
149
+
150
+ UserDetailsインターフェースの実装コード内のisEnabledメソッドをtrueに変更しました。
151
+ ```ここに言語を入力
66
152
  public class UserDetailsImpl implements UserDetails {
67
153
 
154
+
68
155
  private static final long serialVersionUID = 1L;
69
156
  private LoginUser user;
70
157
 
@@ -98,80 +185,162 @@
98
185
  return null;
99
186
  }
100
187
 
101
- @Override
188
+ @Override
102
- public boolean isAccountNonExpired() {
189
+ public boolean isAccountNonExpired() {
103
- // TODO 自動生成されたメソッド・スタブ
190
+ // TODO 自動生成されたメソッド・スタブ
104
- return false;
191
+ return true;
105
- }
192
+ }
106
193
 
107
- @Override
194
+ @Override
108
- public boolean isAccountNonLocked() {
195
+ public boolean isAccountNonLocked() {
109
- // TODO 自動生成されたメソッド・スタブ
196
+ // TODO 自動生成されたメソッド・スタブ
110
- return false;
197
+ return true;
111
- }
198
+ }
112
199
 
113
- @Override
200
+ @Override
114
- public boolean isCredentialsNonExpired() {
201
+ public boolean isCredentialsNonExpired() {
115
- // TODO 自動生成されたメソッド・スタブ
202
+ // TODO 自動生成されたメソッド・スタブ
116
- return false;
203
+ return true;
117
- }
204
+ }
118
205
 
119
- @Override
206
+ @Override
120
- public boolean isEnabled() {
207
+ public boolean isEnabled() {
121
- // TODO 自動生成されたメソッド・スタブ
208
+ // TODO 自動生成されたメソッド・スタブ
122
- return false;
209
+ return true;
123
- }
210
+ }
124
211
 
125
-
126
- }
127
212
  ```
128
213
 
129
- controllerクラス内のメソッドに引数として「@AuthenticationPrincipal UserDetailsImpl userDetails」を設定しています。
130
- そして「System.out.println(userDetails.getUserId());」でユidを取得しようとしていますがnullが返ってきます。
214
+ UserDetailsServiceインタフェスの実装クラス
215
+
131
216
  ```ここに言語を入力
132
- package com.example.demo.controller;
133
217
 
134
- import java.util.List;
218
+ @Service
219
+ public class UserDetailsServiceImpl implements UserDetailsService{
135
220
 
221
+
136
- import org.springframework.beans.factory.annotation.Autowired;
222
+ @Autowired
137
- import org.springframework.security.core.Authentication;
138
- import org.springframework.security.core.annotation.AuthenticationPrincipal;
139
- import org.springframework.security.core.context.SecurityContextHolder;
140
- import org.springframework.stereotype.Controller;
141
- import org.springframework.ui.Model;
223
+ private LoginUserDao userDao;
142
- import org.springframework.web.bind.annotation.GetMapping;
143
224
 
225
+
144
- import com.example.demo.model.User;
226
+ @Override
145
- import com.example.demo.model.UserDetailsImpl;
146
- import com.example.demo.service.UserService;
227
+ public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
147
228
 
148
- @Controller
149
- public class HomeController {
229
+ LoginUser user = userDao.findUser(userName);
150
230
 
231
+ if (user == null) {
232
+
233
+
234
+ throw new UsernameNotFoundException("User" + userName + "was not found in the database");
235
+ }
236
+
237
+ List<GrantedAuthority> grantList = new ArrayList<GrantedAuthority>();
238
+ GrantedAuthority authority = new SimpleGrantedAuthority("USER");
239
+
240
+ grantList.add(authority);
241
+
151
- // インタンスを作成しDIコンテナに格納。
242
+ //rawDataのパワードは渡すことができないので、暗号化
243
+ BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
244
+
245
+ //UserDetailsはインタフェースなのでUserクラスのコンストラクタで生成したユーザオブジェクトをキャスト
246
+ UserDetails userDetails = (UserDetails)new User(user.getUserName(), encoder.encode(user.getPassword()),grantList);
247
+
248
+ return userDetails;
249
+ }
250
+
251
+ }
252
+ ```
253
+ セキュリティコンフィグレーションクラス
254
+
255
+ ```ここに言語を入力
256
+
257
+ @Configuration
258
+ @EnableWebSecurity
259
+ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
260
+
152
261
  @Autowired
153
- UserService userService;
262
+ private UserDetailsServiceImpl userDetailsService;
154
263
 
155
- //userListのアドレスにアクセスした際にGetメソッドを実行。
156
- @GetMapping("/userList")
157
- public String getUserList(Model model,@AuthenticationPrincipal UserDetailsImpl userDetails) {
158
-
159
-
160
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
161
- //Principalからログインユーザの情報を取得
162
- String userName = auth.getName();//ユーザー名は取得できます。
163
- System.out.println(userDetails.getUserId()); // userIdは nullが返ってきます。
164
-
165
- //@Autowiredで作成したインタンスを元に、userServiceのメソッを呼び出
264
+ //フォームの値と比較するDBから取得したワーは暗号化されているのでフォームの値も暗号化るために利用
265
+ @Bean
166
- List<User> userList = userService.selectMany();
266
+ public BCryptPasswordEncoder passwordEncoder() {
167
- //userServiceから受け取ったデータをView側に渡す。
168
- model.addAttribute("userList", userList);
169
- model.addAttribute("userName", userName);
267
+ BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
268
+ return bCryptPasswordEncoder;
269
+ }
170
270
 
271
+ /**
272
+ * 認可設定を無視するリクエストを設定
273
+ * 静的リソース(image,javascript,css)を認可処理の対象から除外する
274
+ */
275
+ @Override
276
+ public void configure(WebSecurity web) throws Exception {
277
+ web.ignoring().antMatchers(
171
- //template配下のファイル名を指定することでViewを呼び出せる。
278
+ "/images/**",
172
- return "userList";
279
+ "/css/**",
280
+ "/javascript/**"
281
+ );
173
282
  }
283
+
284
+ /**
285
+ * 認証・認可の情報を設定する
286
+ * 画面遷移のURL・パラメータを取得するname属性の値を設定
287
+ * SpringSecurityのconfigureメソッドをオーバーライドしています。
288
+ */
289
+ @Override
290
+ protected void configure(HttpSecurity http) throws Exception {
291
+ http
292
+ .authorizeRequests()
293
+ .antMatchers("/", "/home").permitAll() // アクセス制限のないURL
294
+ .anyRequest().authenticated()
295
+ .and()
296
+ .formLogin()
297
+ .loginPage("/login") //ログインページはコントローラを経由しないのでViewNameとの紐付けが必要
298
+ .loginProcessingUrl("/sign_in") //フォームのSubmitURL、このURLへリクエストが送られると認証処理が実行される
299
+ .usernameParameter("username") //リクエストパラメータのname属性を明示
300
+ .passwordParameter("password")
301
+ .defaultSuccessUrl("/userList", true) //認証が成功した際に遷移するURL
302
+ .failureUrl("/login?error") //認証が失敗した際に遷移するURL
303
+ .permitAll() //どのユーザでも接続できる。
304
+ .and()
305
+ .logout()
306
+ .logoutUrl("/logout")
307
+ .logoutSuccessUrl("/login?logout")
308
+ .permitAll();
174
309
  }
310
+
311
+
312
+ @Autowired
313
+ public void configure(AuthenticationManagerBuilder auth) throws Exception{
314
+ auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
315
+ }
316
+
317
+ }
175
318
  ```
176
- 何が原因かわからず詰まっおります。
319
+ mavenではなくgradleを使用しています。
320
+ build gradle
321
+
322
+ ```ここに言語を入力
323
+
324
+
325
+ dependencies {
326
+ compile('org.springframework.boot:spring-boot-starter-data-jpa')
327
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
328
+ implementation 'org.springframework.boot:spring-boot-starter-web'
329
+ compileOnly 'org.projectlombok:lombok'
330
+ developmentOnly 'org.springframework.boot:spring-boot-devtools'
331
+ runtimeOnly 'mysql:mysql-connector-java'
332
+ annotationProcessor 'org.projectlombok:lombok'
333
+ implementation 'org.springframework.boot:spring-boot-starter-security'
334
+ // https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity5
335
+ compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity5', version: '3.0.4.RELEASE'
336
+ // https://mvnrepository.com/artifact/javax.persistence/javax.persistence-api
337
+ compile group: 'javax.persistence', name: 'javax.persistence-api', version: '2.2'
338
+ testImplementation('org.springframework.boot:spring-boot-starter-test') {
339
+ exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
340
+ }
341
+ }
342
+
343
+
344
+ ```
345
+
177
- 何卒よろくお願たします。
346
+ 他のコードも必要でたら追記いたします。