Spring Security入門
はじめに
Spring Securityは、Spring Frameworkベースのアプリケーションに認証・認可の機能を提供するフレームワークです。この記事では、Spring Securityの基本的な設定と使用方法について解説します。
基本的な設定
1. 依存関係の追加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. 基本的なセキュリティ設定
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.permitAll()
)
.logout(logout -> logout
.logoutSuccessUrl("/login?logout")
.permitAll()
);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
認証の実装
1. ユーザーサービスの実装
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("ユーザーが見つかりません: " + username));
return org.springframework.security.core.userdetails.User
.withUsername(user.getUsername())
.password(user.getPassword())
.roles(user.getRoles().toArray(new String[0]))
.build();
}
}
2. ユーザーエンティティの定義
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String username;
private String password;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> roles = new HashSet<>();
// getters and setters
}
認可の実装
1. メソッドレベルのセキュリティ
@Service
public class UserService {
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long userId) {
// ユーザー削除処理
}
@PreAuthorize("hasRole('USER')")
public User getCurrentUser() {
// 現在のユーザー情報取得
}
}
2. コントローラーレベルのセキュリティ
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/profile")
@PreAuthorize("isAuthenticated()")
public UserProfile getProfile() {
// プロフィール情報の取得
}
@PostMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public void adminOperation() {
// 管理者操作
}
}
セキュリティの基本機能
1. パスワードエンコーディング
@Service
public class UserRegistrationService {
@Autowired
private PasswordEncoder passwordEncoder;
public void registerUser(UserRegistrationDto dto) {
User user = new User();
user.setUsername(dto.getUsername());
user.setPassword(passwordEncoder.encode(dto.getPassword()));
user.setRoles(Collections.singleton("USER"));
userRepository.save(user);
}
}
2. CSRF保護
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.ignoringRequestMatchers("/api/**") // APIエンドポイントではCSRF保護を無効化
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
);
return http.build();
}
}
セキュリティのベストプラクティス
-
パスワードの取り扱い
- 強力なパスワードエンコーダーの使用
- パスワードのハッシュ化
- ソルトの使用
-
セッション管理
- セッションタイムアウトの設定
- 同時ログインの制御
- セッション固定攻撃への対策
-
エラーハンドリング
- 適切なエラーメッセージ
- ログイン失敗の制限
- アカウントロックアウト
-
セキュリティヘッダー
- XSS対策
- クリックジャッキング対策
- HSTSの設定
実装例:ログインフォーム
<form th:action="@{/login}" method="post">
<div>
<label>ユーザー名:</label>
<input type="text" name="username" required/>
</div>
<div>
<label>パスワード:</label>
<input type="password" name="password" required/>
</div>
<div>
<input type="submit" value="ログイン"/>
</div>
</form>
まとめ
Spring Securityは、アプリケーションに強力なセキュリティ機能を提供します。適切な設定と実装により、安全なアプリケーションを構築することができます。
参考資料
- Spring Security公式ドキュメント
- OWASPセキュリティガイドライン
- Spring Boot Reference Guide