(Spring Security)ログイン認証時のカラム名(username, password)を任意のカラム名に変更する方法
- 評価
- クリップ 0
- VIEW 3,909
お世話になります。
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>
以上となります。宜しくお願い申し上げます。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
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の内容を以下のようにする
[WebSecurityConfig.java]
// パッケージ省略
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Value("${spring.queries.users-query}")
private String usersQuery;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery("select login_id as username, authority from authorities where login_id = ?")
.dataSource(dataSource);
}
}
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は不要となります。
まぁ、こんなこともできるということで試してみてください。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
質問への追記・修正の依頼でのやりとりから...
6.3. 認証
上記URLのページで「ユーザ情報取得クエリ」の箇所で書かれているとおりSQLを修正することで対応できると思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
asahina1979さんのコメントを元に...
元々の構成で
・MemberEntity.javaの変更点
usernameの代わりにloginIdを定義(getterも)
・MemberRepository.javaの変更点
public MemberEntity findByUsername(String username); → public MemberEntity findByLoginId(String username);
でいけるみたいです。こっちの方が楽っすねw。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.34%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
unz.hori
2018/02/22 16:03
質問の主旨が良く分かりません。usernameの代わりにlogin_idというカラム名を使うにはどうすればいいですか?ということでしょうか?
_cocapeach
2018/02/22 16:23
unz.hori様 いつもお世話になっております。わかりづらい内容で申し訳ありません。unz.hori様のおっしゃっている意味であっています。現在は、DB内のusernameカラムとpasswordカラムで認証を行っているのですが、usernameカラムをlogin_idというカラム名に変更したいのです。その際に、Spring側ではどこを修正すればいいのかわからず困っています。 ログイン認証は右記のサイトを参考にしています。参考サイト(https://qiita.com/knamae/items/8128c7eaa687296470d7)
asahina1979
2018/02/22 19:31
丸パクリできるソースは基本ないです
asahina1979
2018/02/22 19:59
変えたい場所をすでにあなたは変更してますが何がわからないんでしょうか?
_cocapeach
2018/02/22 20:04
asahina1979様 usernameではなくlogin_idというカラム名で認証を行いたいのですが、すでに変更してあるというのはどの箇所でしょうか?