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

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

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

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

Q&A

解決済

3回答

7414閲覧

(Spring Security)ログイン認証時のカラム名(username, password)を任意のカラム名に変更する方法

_cocapeach

総合スコア20

Spring Boot

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

0グッド

0クリップ

投稿2018/02/22 06:26

編集2018/02/22 07:46

お世話になります。

Spring BootとSpring Securityを使用して、ログイン認証を実装しています。
デフォルトでは、DBにusernameとpasswordのカラムを持っていないといけないと思うのですが、
usernameをlogin_idというカラムで持ちたいと思っています。

実装方法を調べたのですが、ログイン認証の実装方法が自分と違っていたので、
参考にはなりませんでした。

ご教示頂けますと幸いです。

フォルダ階層

現時点のデフォルトのまま実装しているソースコードを記載致します。

//LoginController.java package com.sample; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class LoginController { public static final String PAGE = "/login"; private static final String HTML = "login"; @RequestMapping(value = LoginController.PAGE) public String top(Model model) { return LoginController.HTML; } }
//TopController.java package com.sample; import java.security.Principal; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class TopController { public static final String PAGE = "/"; private static final String HTML = "top"; @RequestMapping(value = TopController.PAGE, method = RequestMethod.GET) public String top(Principal principal, Model model) { Authentication authentication = (Authentication) principal; MemberEntity user = (MemberEntity) authentication.getPrincipal(); model.addAttribute("user", user); return TopController.HTML; } }
//MemberEntity.java package com.sample; import java.util.Collection; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; @Entity @Table(name = "member") public class MemberEntity implements UserDetails { private static final long serialVersionUID = 1667698003975566301L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(nullable = false, unique = true) private String username; @Column(nullable = false) private String password; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return null; } @Override public String getPassword() { return this.password; } @Override public String getUsername() { return this.username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
//MemberRepository.java package com.sample; import org.springframework.data.jpa.repository.JpaRepository; public interface MemberRepository extends JpaRepository<MemberEntity, Long> { public MemberEntity findByUsername(String username); }
//MemberServiseImpl.java package com.sample; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @Service public class MemberServiceImpl implements UserDetailsService { private MemberRepository memberRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if (StringUtils.isEmpty(username)) { throw new UsernameNotFoundException(""); } MemberEntity memberEntity = memberRepository.findByUsername(username); if (memberEntity == null) { throw new UsernameNotFoundException(""); } return memberEntity; } @Autowired public void setMemberRepository(MemberRepository memberRepository) { this.memberRepository = memberRepository; } }
//WebSecurityConfig.java package com.sample; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private UserDetailsService userDetailsService; @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.authorizeRequests().anyRequest().authenticated(); httpSecurity.formLogin().loginPage(LoginController.PAGE).usernameParameter("user") .passwordParameter("pass").permitAll(); httpSecurity.logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout**")) // ログアウト処理のパス .logoutSuccessUrl("/login"); } @Override protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { authenticationManagerBuilder.userDetailsService(this.userDetailsService) .passwordEncoder(NoOpPasswordEncoder.getInstance());; } @Autowired public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } }
//Login.html <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>ログイン</title> <meta http-equiv="Content-type" content="text/html; charset=UTF-8" /> </head> <body> <form action="" th:action="@{/login}" method="post"> <p> ユーザーID: <input type="text" name="user" /> </p> <p> パスワード: <input type="password" name="pass" /> </p> <p> <input type="submit" value="ログイン" /> </p> </form> <div th:if="${session['SPRING_SECURITY_LAST_EXCEPTION']} != null"> <span th:text="${session['SPRING_SECURITY_LAST_EXCEPTION'].message}"></span> </div> </body> </html>

以上となります。宜しくお願い申し上げます。

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

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

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

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

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

unz.hori

2018/02/22 07:03

質問の主旨が良く分かりません。usernameの代わりにlogin_idというカラム名を使うにはどうすればいいですか?ということでしょうか?
_cocapeach

2018/02/22 07:23

unz.hori様 いつもお世話になっております。わかりづらい内容で申し訳ありません。unz.hori様のおっしゃっている意味であっています。現在は、DB内のusernameカラムとpasswordカラムで認証を行っているのですが、usernameカラムをlogin_idというカラム名に変更したいのです。その際に、Spring側ではどこを修正すればいいのかわからず困っています。 ログイン認証は右記のサイトを参考にしています。参考サイト(https://qiita.com/knamae/items/8128c7eaa687296470d7)
退会済みユーザー

退会済みユーザー

2018/02/22 10:31

丸パクリできるソースは基本ないです
退会済みユーザー

退会済みユーザー

2018/02/22 10:59

変えたい場所をすでにあなたは変更してますが何がわからないんでしょうか?
_cocapeach

2018/02/22 11:04

asahina1979様 usernameではなくlogin_idというカラム名で認証を行いたいのですが、すでに変更してあるというのはどの箇所でしょうか?
guest

回答3

0

asahina1979さんのコメントを元に...

元々の構成で

・MemberEntity.javaの変更点
usernameの代わりにloginIdを定義(getterも)

・MemberRepository.javaの変更点
public MemberEntity findByUsername(String username); → public MemberEntity findByLoginId(String username);

でいけるみたいです。こっちの方が楽っすねw。

投稿2018/02/23 09:09

unz.hori

総合スコア1057

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

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

0

ベストアンサー

Spring Bootだと定義系(xml)などを必要としないようになっているため余りデフォルトのものを変える事はしない方がいいですね。とりあえず、AuthenticationManagerBuilder.jdbcAuthenticationを使用すればSQLで指定できそうなのでその方法を記述します。※.別途ロール用のテーブルが必要になります。

・application.propertiesにユーザを検索するSQLを定義する

[application.properties] spring.datasource.url=jdbc:mysql://IPアドレス/DB名 spring.datasource.username=ユーザ名 spring.datasource.password=パスワード spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.queries.users-query=select login_id as username, password, true as enabled from テーブル名 where login_id=?

・WebSecurityConfig.javaの内容を以下のようにする

Java

1[WebSecurityConfig.java] 2 3// パッケージ省略 4 5import javax.sql.DataSource; 6 7import org.springframework.beans.factory.annotation.Autowired; 8import org.springframework.beans.factory.annotation.Value; 9import org.springframework.context.annotation.Configuration; 10import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 11import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 12import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 13 14@Configuration 15@EnableWebSecurity 16public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 17 18 @Autowired 19 private DataSource dataSource; 20 21 @Value("${spring.queries.users-query}") 22 private String usersQuery; 23 24 @Override 25 protected void configure(AuthenticationManagerBuilder auth) 26 throws Exception { 27 28 auth.jdbcAuthentication() 29 .usersByUsernameQuery(usersQuery) 30 .authoritiesByUsernameQuery("select login_id as username, authority from authorities where login_id = ?") 31 .dataSource(dataSource); 32 } 33}

autoritiesByUsernameQueryメソッドで指定しているSQLもuserByUsernameQueryメソッドで指定しているようにapplication.propertiesに定義したSQLを指定可能。(直書きも出来るという例)

autoritiesByUsernameQueryで指定しているようなROLE用のテーブルが必要になるので作成してください。authorityカラムには"ROLE_USER"とか入ります。

私が検証用に作成したテーブル
テーブル名:authorities
カラム1:login_id varchar(20) Not NULL
カラム2:authority varchar(20) Not NULL
主キーはlogin_id
login_idはmemberテーブルのlogin_idと同じ値
authorityは'USER_ROLE'とか'ADMIN_ROLE'とか入れます。(使用用途は不明)
※.ROLEに関してはSpring Securityの資料を探ってください。

MemberEntity.java/MemberRepository.java/MemberServiceImpl.javaは不要となります。

まぁ、こんなこともできるということで試してみてください。

投稿2018/02/23 06:35

unz.hori

総合スコア1057

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

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

_cocapeach

2018/02/23 06:51

お手数をお掛けいたしました。 色々とご教示頂き、誠に有難うございました。
退会済みユーザー

退会済みユーザー

2018/02/23 08:52

まあ本当は repositoryインタフェースに findBy からはじまる PHPでいうところのマジックメソッド方式でいいんだけどね。 findBy + entityのフィールド名 + [[ And + entityのフィールド名 ] And + entityのフィールド名 ](対応する引数) の形式
unz.hori

2018/02/23 08:54

なるほどそういうやり方もありますか。
guest

0

質問への追記・修正の依頼でのやりとりから...
6.3. 認証
上記URLのページで「ユーザ情報取得クエリ」の箇所で書かれているとおりSQLを修正することで対応できると思います。

投稿2018/02/22 07:27

unz.hori

総合スコア1057

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

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

unz.hori

2018/02/22 07:33

上記はカラム名をSQLで読み替えている例で修正コストが少なくて済みます。(修正箇所がSQLのみ) ちなみにSQLはapplicationContext.xmlに定義されていると思います。別な情報も見つけましたがこちらは修正箇所も多く少々ハードルが高いと思われます。Spring Security 使い方メモ 認証・認可:https://qiita.com/opengl-8080/items/032ed0fa27a239bdc1cc
_cocapeach

2018/02/22 07:33

ご回答有難うございます。 sqlを修正するというのは他の参考サイトでも見たのですが、現時点でsqlを書かずに認証しているので、どこに書いていいのかがわかりません。
unz.hori

2018/02/22 07:34

コメが入れ違いになりましたかね。applicationContext.xmlを参照してみて下さい。
_cocapeach

2018/02/22 07:36

現在はapplicationContext.xmlを使わずに認証を行っているのですが、その場合は自分で作成すればよいのでしょうか?また、作成する場合はどのパスに作成するのが正しいのでしょうか?初歩的な質問ばかりで申し訳ありません。
unz.hori

2018/02/22 07:38

ん?使わないでどうやってDBにアクセスしているんですか?
unz.hori

2018/02/22 07:40

配置はWEB-INFの直下らしいですね。ないですか?
_cocapeach

2018/02/22 07:47

質問を編集してフォルダ階層のスクリーンショットを貼りました。WEB-INFの場所がわかりません。
unz.hori

2018/02/22 07:51

使っているのはEclipse?
unz.hori

2018/02/22 07:59

CTRL+Shift+Rを押して出てくるダイアログにapplicationContext.xmlと入力しても見つかりませんか?
_cocapeach

2018/02/22 08:09

出てきませんでした。
unz.hori

2018/02/22 08:40

Spring BootはJPAでDBアクセスしてるのかぁ。じゃあSQL変更方式は無理かな。MemberEntityとMemberServiceを修正する必要がありそう
unz.hori

2018/02/22 08:44

とりあえず、MemberEntityだけ修正してみたら?
_cocapeach

2018/02/22 09:05

MemberEntityにlogin_idカラムを追加してみたものの、変化はなく、その他にどこを修正していいのかわかりません。
unz.hori

2018/02/22 10:16

ちょっと調べるのに時間がかかりそう
_cocapeach

2018/02/22 10:46

お手数おかけしております。 申し訳有りません。
unz.hori

2018/02/23 05:27

一応、調べました。AuthenticationManagerBuilder.jdbcAuthenticationを使えばSQLを指定できるようですが、別途ロール用のテーブルが必要になります。まぁ、知りたければ答えますが...。別途テーブルが必要なので...
_cocapeach

2018/02/23 06:10

unz.hori 様 ご教示頂けますと幸いですが、かなりご面倒をかけてしまいそうなので、unz.hori様にお任せ致します。
unz.hori

2018/02/23 06:11

じゃあ、別途回答に書きます。
_cocapeach

2018/02/23 06:23

恐れ入ります。宜しくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問