TOC
スプリング・セキュリティ
Spring SecurityはSpringファミリーのセキュリティ管理フレームワークで、アプリケーションの2つの主要な領域は "認証 "と "認可 "です。Spring SecurityはSpringプロジェクトのセキュリティフレームワークであり、基盤となるSpring Bootセキュリティモジュールのデフォルトの選択技術です。
この2つの主要な領域がSpring Securityの2つのゴールです。
- "認証 "は、本人が宣言する主体を確立するプロセスです。
- "認可 "は、サブジェクトがアプリケーションでアクションを実行することを許可されているかどうかを決定するプロセスです。認可が必要な時点に到達するために、認証プロセスによってサブジェクトの身元はすでに確立されています。
実験環境の準備
環境の準備:
- JDK1.8
- SpringBoot2.2.1
- Maven 3.2+
- 開発ツール
- IntelliJ IDEA
- smartGit
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
ログレベルの変更
Spring Securityのログレベルを設定します。デフォルトはinfoですが、debugに変更できます。
## logback
logging:
level:
org:
springframework:
security: info
ユーザー名/パスワードの設定
何気なくインターフェイスを書いて、アクセスすると、ログインページの次のイメージにジャンプしますが、なぜですか?mavenの設定だけの導入は、その後、アカウントのパスワードは何ですか?実際には、これはSpring Securityのデフォルトのログインページであり、ページのコードは、jarパッケージ内にあり、デフォルトのユーザー名はuserであり、パスワードはランダムに生成されたuuid形式のパスワードです!
## spring security
spring:
security:
user:
name: nicky
password: 123
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { //auth.inMemoryAuthentication()
auth.inMemoryAuthentication()
.withUser("nicky")
.password(bcryptPasswordEncoder().encode("123"))
.roles("admin");
}
@Bean
public PasswordEncoder bcryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
| bcrypt | password | bcrypt |
| ldap | password | ldap |
| {ldap}password | MD4 | {MD4}password |
| MD5 | password | {MD5}password |
| noop | password | noop |
| pbkdf2 | password | pbkdf2 |
| password | {pbkdf2}password | scrypt |
| SHA-1 | password | SHA-1 |
| SHA-652 | SHA-652 | {SHA-256}password |
| SHA652 | SHA-652 | {SHA-256}password |
データベース検証
展開:ユーザ名とパスワードをデータベース方式で検証したい場合は、UserDetailsServiceメソッドをカスタマイズします:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new CustomPasswordEncoder());
auth.parentAuthenticationManager(authenticationManagerBean());
}
UserDetailsServiceImpl.java
package com.example.springboot.oauth2.service;
import com.example.springboot.oauth2.entity.User;
import com.example.springboot.oauth2.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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;
import java.util.Arrays;
import java.util.List;
/**
* <pre>
*
* </pre>
*
* <pre>
*
* 修正記録
* 修正版: 変更者: 日付: 15:15 内容を変更する:
* </pre>
*/
@Slf4j
@Service("userService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
UserMapper userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user == null){
log.info("ログインユーザー[{}] !",username);
throw new UsernameNotFoundException("ログインユーザー["+username + "] !");
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthority());
}
private List getAuthority() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"));
// return Arrays.asList(Collections.emptyList());
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http // ログインページを設定し、アクセスを許可する
.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login").permitAll()
// 基本ログインを設定する
//.and().httpBasic()
// ログアウトページを設定する
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
// オープンインターフェースアクセス、アクセスにログイン認証は必要ない
.and().authorizeRequests().antMatchers("/oauth/**", "/login/**", "/logout/**").permitAll()
// apiこのインターフェイスには管理者権限が必要である。
.antMatchers("/api/**").hasRole("admin")
// その他のリクエストには認証が必要
.anyRequest().authenticated()
// クロスドメイン保護を無効にする;
.and().csrf().disable();
}
静的リソースをインターセプトしない
設定ファイルに加え
@Override
public void configure(WebSecurity web) throws Exception {
//静的リソースのブロック問題を解決する
web.ignoring().antMatchers("/asserts/**");
web.ignoring().antMatchers("/favicon.ico");
}
ログインページのカスタマイズ
Thymeleafテンプレートエンジンを紹介します:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
F9自動コンパイル用のThymeleafテンプレートエンジンキャッシュを無効にします。
spring:
thymeleaf:
cache: false
POSTはデフォルトのSpring Securityチェックインターフェイスで、インターフェイス名は/loginです。
@Controller
public class LoginController {
@GetMapping(value = {"/login"})
public ModelAndView toLogin() {
return new ModelAndView("login");
}
}
ログインページをPOSTでカスタマイズします。独自のバリデーションインターフェイスを書かない限り、POST /loginは公式のSpring Securityバリデーションインターフェイスです:
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://..rg">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>Signin Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="../static/asserts/css/bootstrap.min.css" th:href="@{asserts/css/bootstrap.min.css}" rel="stylesheet" />
<!-- Custom styles for this template -->
<link href="../static/asserts/css/signin.css" th:href="@{asserts/css/signin.css}" rel="stylesheet"/>
</head>
<body class="text-center">
<form class="form-signin" th:action="@{/login}" method="post">
<img class="mb-4" th:src="@{asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72" />
<h1 class="h3 mb-3 font-weight-normal" >Oauth2.0 Login</h1>
<label class="sr-only" >Username</label>
<input type="text" class="form-control" name="username" required="" autofocus="" value="nicky" />
<label class="sr-only" >Password</label>
<input type="password" class="form-control" name="password" required="" value="123" />
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" /> remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">2019</p>
</form>
</body>
</html>
.loginPage("/login")設定ファイルを修正して、カスタムログインページを指定します。
@Override
protected void configure(HttpSecurity http) throws Exception {
http // ログインページを設定し、アクセスを許可する
.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login").permitAll()
// 基本ログインを設定する
//.and().httpBasic()
// ログアウトページを設定する
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
// オープンインターフェースアクセス、アクセスにログイン認証は必要ない
.and().authorizeRequests().antMatchers("/oauth/**", "/login/**", "/logout/**").permitAll()
// apiこのインターフェイスには管理者権限が必要である。
.antMatchers("/api/**").hasRole("admin")
// その他のリクエストには認証が必要
.anyRequest().authenticated()
// クロスドメイン保護を無効にする;
.and().csrf().disable();
}
Remember me
Remember me機能を有効にすると、ログインに成功した後、ブラウザにクッキーを送信して保存し、後でこのクッキーでページを訪問し、チェックに合格する限り、自由にログインすることができます。
<input type="checkbox" name="remember-me" value="true" /> remember me
@Override
protected void configure(HttpSecurity http) throws Exception {
//Remember Me機能を有効にし、ログインに成功した後、ブラウザにクッキーを送信して保存し、後でこのクッキーのあるページを訪問し、チェックに合格する限り、自由にログインすることができる。
http.rememberMe().rememberMeParameter("remember-me");
}
Remember meにチェックを入れると、ログインに成功します。
コード例ダウンロード:




