Spring bootのSecurity(認可設定)についての質問
Q&A
Closed
解決したいこと
現在解体新書という書籍にて11章のSpring セキュリティのURLの認可という内容に着手しています。
管理者ユーザにてのみ閲覧可能である、アドミン専用画面を作成しましたが、アドミンユーザでログイン後遷移すると500エラーが発生しています。
管理者以外のユーザで遷移すると403エラーに飛ぶのでこちらは正しいと思っています。
解決方法の指摘ございましたら、アドバイス頂きたいです。よろしくお願いいたします。
例)
Ruby on RailsでQiitaのようなWebアプリをつくっています。
記事を投稿する機能の実装中にエラーが発生しました。
解決方法を教えて下さい。
発生している問題・エラー
例)
今回修正したソース
■admin.html(新規追加)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout}">
<head>
<title>アドミン権限専用</title>
</head>
<body>
<div layout:fragment="content">
<div class="header border-bottom mt-2">
<h1 class="h2">アドミン権限専用画面</h1>
</div>
</div>
</body>
</html>
■AdminController.java(新規追加)
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
public class AdminController {
/** アドミン権限専用画面に遷移 */
@GetMapping("/admin")
public String getAdmin() {
return "admin/admin";
}
}
■menu.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout}" xmlns:sec="http://www.thymeleaf.org/extrans/spring-security">
<head>
</head>
<body>
<div layout:fragment="menu" class="bg-light">
<ul class="nav nav-pills nav-stacked">
<li role="presentation">
<a class="nav-link" th:href="@{'/user/list'}">ユーザ一覧</a>
</li>
<li role="presentation" sec:authorize="hasRole('ADMIN')">
<a class="nav-link" th:href="@{'/admin'}">アドミン専用</a>
</li>
</ul>
</div>
</body>
</html>
■SecurityConfig.java
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityCustomizer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
public class SecurityConfig {
@Autowired
private UserDetailsService userDetailsService;
// パスワードの暗号化
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/** セキュリティの対象外を設定 */
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return web -> web.ignoring().requestMatchers(
new AntPathRequestMatcher("/webjars/**"), new AntPathRequestMatcher("/css/**"),
new AntPathRequestMatcher("/js/**"), new AntPathRequestMatcher("/h2-console/**"));
}
/** セキュリティの各種設定 */
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// ログイン不要ページの設定
http
.authorizeHttpRequests()
.requestMatchers("/login").permitAll() //直リンクOK
.requestMatchers("/user/signup").permitAll() //直リンクOK
.requestMatchers("/admin").hasAnyAuthority("ROLE_ADMIN")//権限制御
.anyRequest().authenticated(); // それ以外は直リンクNG
//ログイン処理
http.formLogin()
.loginProcessingUrl("/login")//ログイン処理のパス
.loginPage("/login")//ログインページの指定
.failureUrl("/login?error")//ログイン失敗時の遷移先
.usernameParameter("userId")//ログインページのユーザーID
.passwordParameter("password")//ログインページのパスワード
.defaultSuccessUrl("/user/list", true);//成功後の遷移先
//ログアウト処理
http.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout");
// CSRF対策を無効に設定(一時的)
//http.csrf().disable();
return http.build();
}
/** 認証の設定 */
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = passwordEncoder();
// インメモリ認証
/*
auth
.inMemoryAuthentication()
.withUser("user") // userを追加
.password(encoder.encode("user"))
.roles("GENERAL")
.and()
.withUser("admin") // adminを追加
.password(encoder.encode("admin"))
.roles("ADMIN");
*/
// ユーザーデータ認証
auth
.userDetailsService(userDetailsService)
.passwordEncoder(encoder);
}
}
自分で試したこと
まずADMINユーザ等でログインできなかったので、パスワードをハッシュ化し、改善しました。その後管理者ユーザでもログインできないことを発覚しました。
管理者以外のユーザだと403エラーなので管理者ユーザであることは認識されていそうです。認可設定をqiita等で調べていますが、上手く解消と至っていません・