Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
セキュリティ(ログイン認証)編
アジェンダ
 はじめに
 準備
 認証方式
 ユーザー認証処理
 ユーザー認証処理のカスタマイズ
 パスワードエンコード
 BCryptを使ったパスワードのハッシュ化
 ロール
 ユニットテスト
 静的コンテンツの配置
 まとめ
はじめに
 Spring Securityを用いたログイン認証について説明する
はじめに
 使用ライブラリ&バージョン
■Spring Security 4.0
準備
 Maven依存関係
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
準備
 設定用クラスの作成
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
設定クラスであることを
@Configurationアノテーションで明記 WebMvcSecurityの有効化
既存のAdapterを拡張
準備
 設定用クラスの作成
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
このクラスに様々な設定を記述する
認証方式・ユーザー認証処理
 認証方式とユーザー認証処理を組み合わせる
■認証方式
BASIC認証、Form認証
■ユーザー認証処理(何を基にユーザー認証をするか)
インメモリ(プログラム内固定)、
データベース、LDAP など
認証方式
 設定メソッドの上書き
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
configureメソッドをオーバーライドし、
引数のHttpSecurityに対して
様々な設定を行う
認証方式
 アクセス出来るURLの範囲を決める
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated();
}
HttpSecurityから、
アクセス範囲を決めるクラスを取得
ルート「/」は全ユーザーが
アクセス可能
他のURLは認証が必要
認証方式
 BASIC認証を使用する
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
BASIC認証を使用する
認証方式
 ここまでの状態を試す
http://localhost:8080/test
http://localhost:8080/sample
その他のURLでは
全て認証を求められる
BASIC認証をするよう実装したので
BASIC認証の画面が出る
http://localhost:8080/
ルートURLは全ユーザーが
アクセス可能
(ただし今は未実装なので
Not Foundエラーになる)
認証方式
 以下の画面遷移でForm認証を使用する
ホーム画面
挨拶画面
【Click here】クリック
参考:Securing a Web Application
http://spring.io/guides/gs/securing-web/
URL: /
URL: /hello
認証方式
 以下の画面遷移でForm認証を使用する
ホーム画面
挨拶画面
【Click here】クリック
参考:Securing a Web Application
http://spring.io/guides/gs/securing-web/
URL: /
URL: /hellohttp
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated();
下のアクセス制御により、ルート「/」は
全ユーザーがアクセス出来るので
問題なく表示される
ただしルート「/」以外は
認証が必要になる。
認証方式
 以下の画面遷移でForm認証を使用する
ホーム画面
挨拶画面
【Click here】クリック
参考:Securing a Web Application
http://spring.io/guides/gs/securing-web/
URL: /
URL: /hello
ログイン画面
そのため実際は
間にログイン画面が挟まる
認証方式
 ホーム画面を作成する
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example</title>
</head>
<body>
<h1>Welcome!</h1>
<p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
</body>
</html>
home.html
認証方式
 ホーム画面を作成する
home.html
認証方式
 挨拶画面を作成する
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
<input type="submit" value="Sign Out"/>
</form>
</body>
</html>
hello.html
ログインしたユーザー名が
埋め込まれる
認証方式
 挨拶画面を作成する
hello.html
ログインしたユーザー名が
埋め込まれる
認証方式
 URLとビューを関連付ける
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
}
}
本来はコントローラを作成してビューを制御するが、
今回は簡易版としてWebMvcConfigurerAdapterを
拡張してURLとビューのテンプレートをお手軽に関連付ける
/home もしくは / は home.html を
/hello は hello.html を表示する
認証方式
 設定メソッドを変更する
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
// .httpBasic();
.formLogin()
.loginPage("/login_page")
.usernameParameter("username")
.passwordParameter("password")
.permitAll();
}
BASIC認証をやめて
Form認証を行う 認証のページは /login_page
ユーザー名とパスワードの項目は
username と password
全ユーザーのアクセスを許可する
認証方式
 URLとビューを関連付ける
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login_page").setViewName("login_page");
}
}
ログインページ用の関連付けを追加
認証方式
 ログイン画面を作成する
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example </title>
</head>
<body>
<form th:action="@{/login_page}" method="post">
<div><label> User Name : <input type="text" name="username"/>
</label></div>
<div><label> Password: <input type="password" name="password"/>
</label></div>
<div><input type="submit" value="Sign In"/></div>
</form></body></html>
login_page.html
ユーザー名とパスワードの項目は
username と password
認証方式
 ログイン画面を作成する
login_page.html
認証方式
 ユーザー認証処理に、インメモリ認証を使用する
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
~~ 中略 ~~
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
}
}
HttpSecurityを引数に受けるconfigureメソッドの他に
AuthenticationManagerBuilderを受け取るメソッドがあり、
ユーザー認証処理はここに設定を記述する
認証方式
 ユーザー認証処理に、インメモリ認証を使用する
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
インメモリ認証を行う指定
ユーザーは、user と admin の2つを用意する。
パスワードはいずれも password で、
ロールは user が USERで、adminは USER と ADMIN。
(ロールについては後ほど)
認証方式
 動作確認
http://localhost:8080/
user / password
を入力
userが表示される
admin / password
を入力 admin が表示される
ユーザー認証処理
 データベース登録したにログイン情報で認証処理を試す
ユーザー認証処理
 接続先をapplication.ymlに記述する
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://xxx.xxx.xxx.xxx/database
username: databaseusername
password: xxx
接続先に応じて変更を!
ユーザー認証処理
 ユーザー認証処理をJDBC方式にする
@Autowired
private DataSource dataSource;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth
// .inMemoryAuthentication()
// .withUser("user").password("password").roles("USER").and()
// .withUser("admin").password("password").roles("USER", "ADMIN");
.jdbcAuthentication()
.dataSource(dataSource);
}
}
コンテナが管理している
接続先情報を取得
JDBC方式を指定する
接続先を指定する
ユーザー認証処理
 デフォルトのユーザー情報テーブル
create table users(
username varchar_ignorecase(50) not null primary key,
password varchar_ignorecase(50) not null,
enabled boolean not null
);
create table authorities (
username varchar_ignorecase(50) not null,
authority varchar_ignorecase(50) not null,
constraint fk_authorities_users foreign key(username)
references users(username)
);
create unique index ix_auth_username
on authorities (username,authority);
■Spring Security Reference - 37.1 User Schema より
http://docs.spring.io/spring-security/site/docs/4.0.3.CI-SNAPSHOT/reference/htmlsingle/#user-schema
ユーザー認証処理
 テスト用のユーザーを登録
insert into users values('test_user', 'test', true);
insert into authorities values('test_user', 'ROLE_USER');
ユーザー認証処理
 動作確認
http://localhost:8080/
test_user / test
を入力
test_userが
表示される
ユーザー認証処理のカスタマイズ
 自前の認証処理を実装する
create table user_info (
username varchar(50) not null primary key,
email varchar(50) not null,
password varchar(50) not null,
enabled boolean not null,
authority varchar(50) not null
);
create unique index ix_user_info_email on user_info (email);
以下のテーブルに登録したユーザー情報で認証する
テーブルを新規作成
メールアドレスを登録し、
この値とパスワードで
認証する
insert into user_info values('test_user', 'test@user', 'test',
TRUE, 'ROLE_USER');
サンプルデータ
ユーザー認証処理のカスタマイズ
 ユーザー情報用のエンティティを作成する
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="user_info")
public class UserInfo {
@Id
@GeneratedValue
private String username;
@Column(nullable = false)
private String email;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private Boolean enabled;
@Column(nullable = false)
private String authority;
Lombokを使用
user_infoテーブルの
エンティティとして宣言
カラムに応じた
フィールドを宣言
ユーザー認証処理のカスタマイズ
 ユーザー情報用のエンティティを作成する
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="user_info")
public class UserInfo implements UserDetails {
~~ 中略 ~~
public Collection<GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(authority));
return authorities;
}
UserDetailsに定義された
メソッドを実装
(他も同様に)
Spring Securityの決まりに従って
UserDetailsを実装
ユーザー認証処理のカスタマイズ
 ユーザー情報用のリポジトリを作成する
public interface UserInfoRepository
extends JpaRepository<UserInfo, String> {
public UserInfo findByEmail(String email);
}
メールアドレスで検証する
メソッドを宣言
(実装はJPAに任せる)
先ほどのエンティティを扱うリポジトリ
ユーザー認証処理のカスタマイズ
 自前の認証処理を実装したServiceクラスを作成する
@Service
public class UserInfoService
implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s)
throws UsernameNotFoundException {
return null;
}
}
UserDetailsServiceを
実装する
UserDetailsServiceに
定義されているメソッドを実装する
InMemoryUserDetailsManagerなど
既存の認証処理はこのインターフェースを
実装している
ユーザー認証処理のカスタマイズ
 自前の認証処理を実装したServiceクラスを作成する
@Override
public UserDetails loadUserByUsername(String s)
throws UsernameNotFoundException {
if (s==null || "".equals(s)) {
throw new UsernameNotFoundException("Username is empty");
}
UserInfo userInfo = userInfoRepository.findByEmail(s);
if (userInfo == null) {
throw new UsernameNotFoundException(
"User not found for name: " + s);
}
return userInfo;
}
未入力はエラー
入力されたメールアドレスで検索
検索できなかった場合はエラー
検索できたらそれを返す
ユーザー認証処理のカスタマイズ
 Serviceクラスを使用して認証するよう設定する
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserInfoService userInfoService;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth
.userDetailsService(userInfoService);
// .jdbcAuthentication()
// .dataSource(dataSource);
}
作成したServiceクラスを宣言
JDBC認証から、
作成したServiceクラスでの
認証に切り替える
ユーザー認証処理のカスタマイズ
 動作確認
http://localhost:8080/
test@user / test
を入力
test_userが
表示される
認証はメールアドレス
で行う
ログイン後は
ユーザー名を表示
パスワードエンコード
 パスワードを平文のまま保存するのは危険なのでエンコードして保存し、
認証時に入力されたパスワードをエンコードしてチェックする
ログイン画面
平文パスワード
エンコード
処理
エンコード済み
パスワード
データベース
読み込み
処理
エンコード済み
パスワード
認証
エンコード済みの
パスワードを格納
パスワードエンコード
 ハッシュ値が入るようテーブルを変更
create table user_info (
username varchar(50) not null primary key,
email varchar(50) not null,
password varchar(60) not null,
enabled boolean not null,
authority varchar(50) not null
);
create unique index ix_user_info_email on user_info (email);
以下のテーブルに登録したユーザー情報で認証する
insert into user_info values('test_user', 'test@user',
'$2a$10$fms1eItee/kPxD8FSdnk/uO9bC.CBweUrQE.CLRgZgzIGcFJVcLRu',
TRUE, 'ROLE_USER');
サンプルデータ
パスワードのカラムを拡張
「test」のハッシュ値
パスワードエンコード
 認証プロバイダを変更
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserInfoService userInfoService;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth
.authenticationProvider(createAuthProvider());
// .userDetailsService(userInfoService);
// .jdbcAuthentication()
// .dataSource(dataSource);
} 作成したServiceクラスでの認証から、
後述する認証プロバイダに変更する
パスワードエンコード
 認証プロバイダを変更
auth
.authenticationProvider(createAuthProvider());
// .userDetailsService(userInfoService);
// .jdbcAuthentication()
// .dataSource(dataSource);
}
private AuthenticationProvider createAuthProvider() {
DaoAuthenticationProvider authProvider =
new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userInfoService);
authProvider.setPasswordEncoder(new BCryptPasswordEncoder());
return authProvider;
}
認証プロバイダの作成
認証処理を実装した
Serviceクラスを指定する
パスワードのエンコードに
BCryptエンコーダを使用する
BCryptを使った
パスワードのハッシュ化
 BCryptのハッシュ値
$2a$10$fms1eItee/kPxD8FSdnk/uO9bC.CBweUrQE.CLRgZgzIGcFJVcLRu
BCryptのハッシュ値
insert into user_info values('test_user', 'test@user',
'$2a$10$fms1eItee/kPxD8FSdnk/uO9bC.CBweUrQE.CLRgZgzIGcFJVcLRu',
TRUE, 'ROLE_USER');
サンプルデータ BCryptでハッシュ化したパスワード
ヘッダ ソルト値 22文字 ハッシュ値 32文字
BCryptを使った
パスワードのハッシュ化
 BCryptのヘッダ
$2a$10$fms1eItee/kPxD8FSdnk/uO9bC.CBweUrQE.CLRgZgzIGcFJVcLRu
ヘッダ ソルト値 22文字 ハッシュ値 32文字
2a →
10 →
バージョン番号。
主流は「2a」。
ストレッチング(ハッシュ値の計算を繰り返す)回数の指定。
累乗数を指定する。
10の場合、210なので1,024回繰り返す。
BCryptを使った
パスワードのハッシュ化
 BCryptのソルト値
$2a$10$fms1eItee/kPxD8FSdnk/uO9bC.CBweUrQE.CLRgZgzIGcFJVcLRu
ヘッダ ソルト値 22文字 ハッシュ値 32文字
指定のソルト値とパスワードを基に
指定のストレッチ回数で求めたハッシュ値。
BCryptを使った
パスワードのハッシュ化
 BCryptのハッシュ値
$2a$10$fms1eItee/kPxD8FSdnk/uO9bC.CBweUrQE.CLRgZgzIGcFJVcLRu
ヘッダ ソルト値 22文字 ハッシュ値 32文字
ハッシュ値を求める際に自動生成されるソルト値。
BCryptを使った
パスワードのハッシュ化
 Spring SecurityでのBCryptのハッシュ値の生成方法
String hashedPassword
= BCrypt.hashpw( rawPassword, BCrypt.gensalt() );
ハッシュ化前のパスワード ソルト値の生成
ハッシュ化したパスワード
BCryptクラスを使用
BCryptを使った
パスワードのハッシュ化
 Spring SecurityでのBCryptのハッシュ値の生成方法
String hashedPassword
= BCrypt.hashpw( “testpassword”, BCrypt.gensalt() );
上記コードを3回実行した結果
$2a$10$UmuUZJ4D6IaJMm5.UQdsAef2fz6QQuRyRDYrSFab4uNv2SzNEHFW2
$2a$10$.XMgSGCnfecWXh25jKDoZOojlyaMWODJxpoCcOh0YorGM53Vcxq22
$2a$10$1Cc9rpBWu5NenpYameu2f.nHohPeo0HfRLn7dAwKnhQMLkNdibOd6
「testpassword」のハッシュ値を取得するコード
ソルト値もハッシュ値も違う
3つの値が生成された
ロール
 Spring Securityのユーザごとの権限に応じたアクセス制御
UserDetails
GrantedAuthority
1
0..*
ユーザー名等の情報を保持
そのユーザーの
権限情報を保持
権限情報は
複数持てる 権限情報に応じた
アクセス制御を行う
ロール
 サンプルのテーブル構成と実装
create table user_info (
username varchar(50) not null primary key,
email varchar(50) not null,
password varchar(50) not null,
enabled boolean not null,
authority varchar(50) not null
);
以下のテーブルに登録したユーザー情報で認証する
サンプルのテーブルは
1ユーザー1権限
権限を保持するカラム
public class UserInfo implements UserDetails {
~~ 中略 ~~
public Collection<GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(authority));
return authorities;
}
標準モデルに合わせて
リストで返却
ロール
 サンプルユーザー
insert into user_info values('test_user', 'test@user',
'xxx', TRUE, 'ROLE_USER');
insert into user_info values('admin_user', 'admin@user',
'xxx', TRUE, 'ROLE_ADMIN');
サンプルのユーザー 一般権限ユーザー
管理者権限ユーザー
ロール
 アクセス出来るURLの範囲を変更する
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
~~中略~~
「/admin/」内のURLは
管理者権限ユーザーのみが
アセス出来る
ロール
 動作確認
管理者ユーザーで
ログイン
管理者のみのURLへ
アクセス可能
一般ユーザーで
ログイン 管理者ではないので
「403 Forbidden」
(閲覧禁止)が返ってくる
ユニットテスト
 MockMVCを利用してテストを行う
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = App.class)
public class AppTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.build();
}
ユニットテスト
 MockMVCにSpring Securityの利用を通知
import static org.springframework.security.test.web.servlet.setup.
SecurityMockMvcConfigurers.*;
~~中略~~
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
MockMVCに通知
ユニットテスト
 ログインしないでアクセスするテスト
@Test
public void ログインせずにルートページへアクセス() throws Exception {
mockMvc.perform(get("/"))
.andExpect(status().isOk());
}
@Test
public void ログインせずにハローページへアクセス() throws Exception {
mockMvc.perform(get("/hello"))
.andExpect(status().is3xxRedirection());
}
ログインせずにルートへアクセスする場合は
OKステータスが返ってくる
ログインせずにハローページへアクセスする場合は
300番台(移動通知)のどれか
(正確には302:Moved Temporarily)が
返ってくる
ユニットテスト
 ログインしてアクセスするテスト
@Test
@WithMockUser(username="test@user")
public void ログインしてハローページへアクセス() throws Exception {
mockMvc.perform(get("/hello"))
.andExpect(status().isOk());
}
ログインするユーザを
「WithMockUser」アノテーションで指定
ログインした後なら
OKステータスが返ってくる
ユニットテスト
 権限を指定してアクセスするテスト
@Test
@WithMockUser(username="user@user", roles="USER")
public void 一般ユーザーで管理者ページへアクセス() throws Exception {
mockMvc.perform(get("/admin/adminPage"))
.andExpect(status().is4xxClientError());
}
@Test
@WithMockUser(username="admin@user", roles="ADMIN")
public void 管理者ーザーで管理者ページへアクセス() throws Exception {
mockMvc.perform(get("/admin/adminPage"))
.andExpect(status().isOk());
}
「WithMockUser」アノテーションに
権限を記述
一般ユーザーには権限がないので
400番台(処理失敗)のどれか
(正確には403:Forbidden)が返ってくる
管理者ユーザーならアクセス可能
ユニットテスト
 Formログインにアクセスするテスト
@Test
public void ログインページのテスト() throws Exception {
mockMvc.perform(
formLogin()
.user("username", "test@user")
.password("password", "test")
.loginProcessingUrl("/login_page")
).andExpect(status().isFound())
.andExpect(
authenticated()
.withUsername("test_user")
.withRoles("USER")
);
}
Formログインをする
認証に成功し、
ユーザー名とロールが想定通りか
チェックする
認証情報(今回はメアド)、
パスワード、ログインURLを指定
静的コンテンツの配置
 ログイン前でも画像・CSS・JavaScript等は参照可能とする
<div><input type="submit" value="Sign In"/></div>
</form>
<img src="/img/test.png"/>
ログイン前は何も設定しないと、
静的コンテンツにアクセス出来ない
静的コンテンツは
resources/static に配置
静的コンテンツの配置
 ログイン前でも画像・CSS・JavaScript等は参照可能とする
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/js/**", "/img/**");
}
除外リストに静的コンテンツを記述
ログイン前でも静的コンテンツへの
アクセスが行えるようになった
まとめ
 参考
■Spring Security Reference
http://docs.spring.io/spring-security/site/docs/4.0.3.CI-
SNAPSHOT/reference/htmlsingle/
■Spring Bootでユーザ認証 | memorandum
http://ksoichiro.blogspot.jp/2015/03/spring-boot.html
■Spring Boot でログイン画面 + 一覧画面 + 登録画面の Webアプリケーションを作る ( その10 )( ロ
グイン画面作成3 ) - かんがるーさんの日記
http://ksby.hatenablog.com/entry/2015/02/08/030648#LoginControllerTest.java
■BCrypt(Blowfish暗号)について調べたので文書化してみました
http://www.kamiya54.info/post/100503173956/bcryptblowfish%E6%9A%97%E5%8F
%B7%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E8%AA%BF%E3%81%B
9%E3%81%9F%E3%81%AE%E3%81%A7%E6%96%87%E6%9B%B8%E5%8C%96%
E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%81%9F

More Related Content

Spring bootでweb セキュリティ(ログイン認証)編