尝试使用Spring Boot和Spring Security(SecurityFilterChain)
首先
我在个人学习中正在开发的web服务中尝试添加登录功能,原本打算使用之前学习过的Spring Security,但由于WebSecurityConfigurerAdapter已经被弃用,所以我进行了其他的调查。
这次也兼具输出的目的,我将进行发布。
不推荐的写法(WebSecurityConfigurerAdapter)
@Configuration
@EnablebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http)throws Exception {
// do something
}
}
正如我之前所述,我继承的WebSecurityConfigurerAdapter已经过时了,我不知道其他的方法,感到非常困惑…
我觉得在Spring Boot的参考书中,只有这种方法被提到得比较多。
(如果有其他方法和详细说明的参考书,请告诉我。)
得出的結論
建议我们使用「SecurityFilterChain」。
具体的例子 (jù tǐ lì zǐ)
以下是基本的设置方式。
package com.example.config;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.formLogin(login -> login
// 指定したURLがリクエストされるとログイン認証を行う。
.loginProcessingUrl("/login")
// ログイン時のURLの指定
.loginPage("/login")
// 認証成功後にリダイレクトする場所の指定
.defaultSuccessUrl("/")
// ログインに失敗した時のURL
.failureUrl("/login?error")
//アクセス権限の有無(permitAllは全てのユーザーがアクセス可能)
.permitAll()
).logout(logout -> logout
.logoutSuccessUrl("/")
//アクセス制限
).authorizeHttpRequests(ahr -> ahr
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.mvcMatchers("/").permitAll()
//"/admin"はADMIN権限のあるものだけがアクセスできる
.mvcMatchers("/admin").hasRole("ADMIN")
//他のリンクは全て認証が必要である。
.anyRequest().authenticated()
);
/**
* HttpSecurityオブジェクトを生成し、オブジェクトもしくはnullを返す。
* build()メソッドはHttpSecurityBuilderインターフェースのメソッド。
* HttpSecurityBuilderは、
* HttpSecurity、WebSecurityなどの実装クラス
* HttpSecurityは、DefaultSecurityFilterChainインターフェースを実装しており、
* DefaultSecurityFilterChainはSecurityFilterChainを実装しているため、ポリモーフィズム的にも正しい。
*/
return http.build();
}
}
与以前不同的是,
①不再需要继承WebSecurityConfigurerAdapter。
不再需要覆盖configure方法。
由于方法使用了Lambda表达式,所以处理稍微有些难懂。(※: 被称为Lambda DSL)
需要将SecurityFilterChain注册为Bean,并作为返回值返回。 (http.build()生成HttpSecurity对象并返回为返回值)
这种感觉是存在的。
关于这个SecurityFilterChain并不是新的,似乎很早以前就有了,但是似乎无法注册SecurityFilterChain作为Bean,从Spring Security 5.4开始,似乎可以注册Bean了。
请查看官方博客以了解更详细的信息。
■公式博客↓
关于补充(Lambda DSL)
Lambda DSL,中文翻译为”Lambda领域特定语言”。
简单来说,
通过使用Λ可以扩展DSL来设置HTTP安全性。
听起来像是这样的情况。
虽然我还没有完全理解,但根据看了官方博客的感觉,似乎有以下优势。
只需要一个选项,对以下内容进行中文本地化改写:
①不再需要使用and()方法进行连接。
②结果是可读性提高(代码变得更易读)。
确实,每次进行formLogin(登录时的认证),authorizeRequests(访问控制),logout(登出时的设置)等设置时都使用and()方法进行连接,写起来很麻烦,而且方法越来越多,阅读起来有些困难。?
确实,每次要进行formLogin(登录时的认证)、authorizeRequests(访问控制)和logout(登出时的设置)等设置时,都需要使用and()方法进行连接,这样写起来很繁琐,而且随着方法增多,阅读起来也变得有些困难。?
具體的例子
最后,我们来确认一下实际使用Lambda DSL和不使用Lambda DSL的例子。
■使用Lambda DSL的例子
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests ->
authorizeRequests
.antMatchers("/blog/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(formLogin ->
formLogin
.loginPage("/login")
.permitAll()
)
.rememberMe(withDefaults());
}
}
不使用Lambda DSL的案例。
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/blog/**").permitAll()
.anyRequest().authenticated()
.and() // ←ここ
.formLogin()
.loginPage("/login")
.permitAll()
.and() // ←ここ
.rememberMe();
}
}
公式博客(关于Lambda DSL)↓
资料、文献、引用资料、引证资料
■ 公式博客
■有关Spring Security的Qiita投稿
■ HttpSecurity 类
■DefaultSecurityFilterChain类
■安全过滤器链接口
■httpSecurityBuilder接口
■Spring Security的配置