質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

2回答

15459閲覧

Spring Securityを拡張したいが、ログインが上手くいかない

omou

総合スコア11

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

2クリップ

投稿2017/10/11 12:31

編集2017/10/11 12:34

Spring Securityを拡張して「ユーザー名」「パスワード」のほかに「チームID」という文字列を認証処理の要素として追加したいのですが、ログイン後意図したURLに遷移せずに、ルート「"/"」に遷移して404エラーが発生してしまいます。(ログを見た感じだと認証自体は成功しているように見えます。)

一点気になっているのが、WebSecurityConfigクラスにてaddFilter()の記述を除外すると、意図したURLへ遷移します(ログイン中のユーザー情報を取得できずNullPointerExceptionが発生してしまいますが)

とりあえず具体的なログイン処理は後回しにしてDBから「ユーザー名」「パスワード」「チームID」を取得し、それらをそのまま認証情報として受け取り、ログイン成功させる所まで行きたいです。

以下ソースを記載します。(いろいろなサイトを参考にして試行錯誤しているため、読みづらく無駄な部分があるかと思います。。)
長くなってしまい大変恐縮ですが、宜しくお願い致します。

java

1 2@EnableWebSecurity 3@Component 4public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 5 6 private final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class); 7 8 // 認証 9 @Autowired 10 private UserDaoAuthenticationProvider userDaoAuthenticationProvider; 11 @Autowired 12 private UserDetailsService userDetailsService; 13 14 // 暗号化 15 @Autowired 16 private BCryptPasswordEncoder bCryptPasswordEncoder; 17 18 @Autowired 19 private UserAuthenticationFilter userAuthenticationFilter; 20 21 @Override 22 protected void configure(HttpSecurity httpSecurity) throws Exception { 23 logger.info("WebSecurityConfig configure"); 24 25 httpSecurity.csrf(); 26 27 httpSecurity.authorizeRequests().antMatchers(LoginController.PAGE).permitAll().anyRequest().authenticated().and() 28 .formLogin().loginPage(LoginController.PAGE).successForwardUrl(ProjectManageController.PAGE).defaultSuccessUrl(ProjectManageController.PAGE, false).failureUrl("/error").usernameParameter("user_name").passwordParameter("user_password").permitAll().and().authenticationProvider(userDaoAuthenticationProvider).addFilter(userAuthenticationFilter); 29 // Filter消すとdefaultURL反映される 30 //.formLogin().loginPage(LoginController.PAGE).successForwardUrl(ProjectManageController.PAGE).defaultSuccessUrl(ProjectManageController.PAGE, false).failureUrl("/error").usernameParameter("user_name").passwordParameter("user_password").permitAll().and().authenticationProvider(userDaoAuthenticationProvider); 31 32 33 } 34 35 @Override 36 public void configure(WebSecurity web) throws Exception { 37 web.ignoring().antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/lib/**"); 38 } 39 40 @Autowired 41 public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 42 logger.info("configureGlobal AuthenticationManagerBuilder start"); 43 logger.info(auth.toString()); 44 auth.authenticationProvider(userDaoAuthenticationProvider).userDetailsService(this.userDetailsService).passwordEncoder(bCryptPasswordEncoder); 45 logger.info(auth.getDefaultUserDetailsService().toString()); 46 logger.info("configureGlobal AuthenticationManagerBuilder end"); 47 } 48 49 @Autowired 50 @Override 51 protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { 52 logger.info("configure AuthenticationManagerBuilder"); 53 authenticationManagerBuilder.authenticationProvider(userDaoAuthenticationProvider).userDetailsService(this.userDetailsService).passwordEncoder(bCryptPasswordEncoder);// 入力値をbcryptでハッシュ化した値でパスワード認証を行うように設定 54 } 55 56 @Autowired 57 public void setUserDetailsService(UserDetailsService userDetailsService) { 58 logger.info("setUserDetailsService"); 59 this.userDetailsService = userDetailsService; 60 } 61} 62

java

1package com.omoumou.gantt.web.login; 2 3 4@Component 5public class UserAuthenticationFilter extends UsernamePasswordAuthenticationFilter { 6 7 private static final Logger logger = LoggerFactory.getLogger(UserAuthenticationFilter.class); 8 9 @Autowired 10 UserMapper userMapper; 11 12 @Autowired 13 private BCryptPasswordEncoder bCryptPasswordEncoder; 14 15 16 // これがないとだめらしい。フィールド形式のAutowiredだとエラーになる 17 @Autowired 18 public void setAuthenticationManager(AuthenticationManager authenticationManager) { 19 super.setAuthenticationManager(authenticationManager); 20 } 21 22 23 @Override 24 public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { 25 logger.info("UserAuthenticationFilter attemptAuthentication"); 26 if (!request.getMethod().equals("POST")) { 27 throw new AuthenticationServiceException("Authentication method not supported: " 28 + request.getMethod()); 29 } 30 31 setUsernameParameter("user_name"); 32 setPasswordParameter("user_password"); 33 String username = super.obtainUsername(request); 34 String password = super.obtainPassword(request); 35 String teamId = obtainTeamId(request); 36 37 38 logger.info("debug001:" + request); 39 logger.info("debug001:" +request.getHeaderNames()); 40 logger.info("debug001:" +request.getLocalAddr()); 41 logger.info("debug001:" + teamId); 42 logger.info("debug001:" + username); 43 logger.info("debug001:" + password); 44 45 46 47 // username required 48 if (!StringUtils.hasText(username)) { 49 logger.info("UserName is required"); 50 throw new AuthenticationServiceException("UserName is required"); 51 } 52 53 LoginUserModel loginUserModel = userMapper.loginUserCheck(username, teamId); 54 55 // 動作確認のためお試し 56 if(loginUserModel != null){ 57 logger.info("debug001: " + loginUserModel.getUserName()); 58 boolean isLoginSsuccess = bCryptPasswordEncoder.matches(password, loginUserModel.getUserPassword()); 59 60 if (!isLoginSsuccess) { 61 logger.info("debug001:パスワードが正しくありません。"); 62 throw new AuthenticationCredentialsNotFoundException("ログイン情報が存在しません。"); 63 }else{ 64 65 logger.info("debug001:パスワードが正しいお"); 66 } 67 } 68 69 70 UserAuthenticationToken authRequest = new UserAuthenticationToken(username, password, teamId); 71 72 // Allow subclasses to set the "details" property 73 setDetails(request, authRequest); 74 75 return this.getAuthenticationManager().authenticate(authRequest); 76 } 77 78 protected String obtainTeamId(HttpServletRequest request) { 79 return request.getParameter("team_id"); 80 } 81}

java

1package com.omoumou.gantt.web.login; 2 3public class UserAuthenticationToken extends UsernamePasswordAuthenticationToken { 4 5 private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; 6 7 private static final Logger logger = LoggerFactory.getLogger(UserAuthenticationToken.class); 8 9 //チームID 10 private final String teamId; 11 12 public UserAuthenticationToken(Object principal, Object credentials, String teamId) { 13 super(principal, credentials); 14 this.teamId = teamId; 15 logger.info("UserAuthenticationToken 1 "); 16 } 17 18 public UserAuthenticationToken(Object principal, Object credentials, String teamId, Collection<? extends GrantedAuthority> authorities) { 19 super(principal, credentials, authorities); 20 this.teamId = teamId; 21 logger.info("UserAuthenticationToken 2 "); 22 } 23 24 public String getTeamId() { 25 return this.teamId; 26 } 27}

java

1package com.omoumou.gantt.web.login; 2 3@Component 4public class UserDaoAuthenticationProvider extends DaoAuthenticationProvider { 5 6 private static final Logger logger = LoggerFactory.getLogger(UserDaoAuthenticationProvider.class); 7 8 @Autowired 9 private UserDetailsService userDetailsService; 10 11 @Autowired 12 UserMapper userMapper; 13 14 @Autowired 15 private BCryptPasswordEncoder bCryptPasswordEncoder; 16 17 18 @Autowired 19 private UserAuthenticationFilter userAuthenticationFilter; 20 21 // TODO: 以下のメソッドをOverrideしないとUserDetails must be setのエラーが発生してしまう。(継承元のクラスでエラーがでいていた) 22 @Override 23 protected void doAfterPropertiesSet() throws Exception { 24 logger.info("doAfterPropertiesSet start"); 25 logger.info("doAfterPropertiesSet userDetailsService: " + userDetailsService.getClass()); 26 } 27 28 @Override 29 public Authentication authenticate(Authentication auth) throws AuthenticationException { 30 31 logger.info("authenticate start"); 32 33 String username = auth.getName(); 34 String password = auth.getCredentials().toString(); 35 logger.info("authenticate username: " + username); 36 logger.info("authenticate password: " + password); 37 logger.info("authenticate end"); 38 39 return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), auth.getAuthorities()); 40 } 41 42 @Override 43 protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { 44 super.additionalAuthenticationChecks(userDetails, authentication); 45 logger.info("additionalAuthenticationChecks start"); 46 UserAuthenticationToken companyIdUsernamePasswordAuthentication = (UserAuthenticationToken) authentication; 47 String requestedCompanyId = companyIdUsernamePasswordAuthentication.getTeamId(); 48 String companyId = ((LoginUser) userDetails).getUser().getTeamId(); 49 50 if (!companyId.equals(requestedCompanyId)) { 51 throw new BadCredentialsException(messages.getMessage( 52 "AbstractUserDetailsAuthenticationProvider.badCredentials", 53 "Bad credentials")); 54 } 55 } 56 57 @Override 58 protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) { 59 String companyId = ((LoginUser) user).getUser().getTeamId(); 60 return new UserAuthenticationToken(user, authentication.getCredentials(), companyId, user.getAuthorities()); 61 } 62 63 @Override 64 public boolean supports(Class<?> token) { 65 logger.info("supports"); 66 return UsernamePasswordAuthenticationToken.class.isAssignableFrom(token); 67 } 68} 69

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

フィルターで認証状態(setAuthenticated)で正常(true)を設定したオブジェクトを返却してないからでは?

投稿2017/10/11 23:33

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

omou

2017/10/12 13:12

ご回答ありがとうございます。 this.getAuthenticationManager().authenticate(authRequest).isAuthenticated() の結果がtrueとなっているので認証正常となっている認識でいたのですが違うのでしょうか? ちなみに setAuthenticated(true) を記述すると、 java.lang.IllegalArgumentException: Cannot set this token to trusted のエラーが発生してしまいます。
退会済みユーザー

退会済みユーザー

2017/10/12 15:27

この実装のだとそうなるのか。 利用している XxxxxController.PAGE の設定によりけりでわかるかもしれないな。 isAuthenticated で true が返ってくるならウチの推測は誤りです。
guest

0

自己解決

UserAuthenticationFilterクラスを使用すると(WebSecurityConfigでaddFiltrを設定すると)
、AbstractAuthenticationTargetUrlRequestHandlerクラスのフィールド「defaultTargetUrl」の値が「/」に書き換わっておりました。
※UserAuthenticationFilterクラスを使用しない場合だと、defaultTargetUrlの値は遷移先URLとなっており、ログイン後意図したページへ遷移でる

これはUserAuthenticationFilterクラスの何らかの処理がログイン後遷移先のURLをデフォルトの値に書き換えてしまっていたということなのでしょうか?

とりあえずUserAuthenticationFilterクラスのattemptAuthenticationメソッド内に以下の処理を記述するとログイン後意図したURLに遷移し、ログイン処理が成功することを確認しました。

SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter(ProjectManageController.PAGE);
successHandler.setDefaultTargetUrl(ProjectManageController.PAGE);
successHandler.setAlwaysUseDefaultTargetUrl(true);
setAuthenticationSuccessHandler(successHandler);

疑問は残りますが、本件については解決となりますのでクローズとさせていただきます。

お忙しい中ご回答していただき、有難うございました。

投稿2017/10/18 23:20

omou

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問