Spring Security的匿名身份认证

正如公式文档中的”Anonymous Authentication”所述,在安全性方面,除了授予权限的事物外,一切皆应拒绝更好。当在web中使用spring-security时,这将通过过滤器链来实现。在此过程中,经过认证的用户将通过过滤器链,而未经认证的用户将绕过它,这可能会对未经认证的用户造成不便。因此,spring-security提供了匿名认证用户。实质上,它被视为未经认证的认证用户。

下面的示例代码是基于spring-security 6。build.gradle文件如下所示。

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.0.3'
	id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.springframework.security:spring-security-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

在控制器中,两者易于理解的行为差异在于获取认证对象Authentication及其类型。参考:Spring MVC官方文档中有关使用匿名认证的部分。

  @GetMapping("/sample")
  String sample(Authentication authentication, @CurrentSecurityContext SecurityContext context) {
    ...

如果使用anonymous身份,则Authentication参数将为空。如果想避免此情况,请使用@CurrentSecurityContext。

状態認証済み未認証(anonymous)AuthenticationUsernamePasswordAuthenticationTokennull@CurrentSecurityContextUsernamePasswordAuthenticationTokenAnonymousAuthenticationToken

因此,由於”anonymous”在默認情況下具有”ROLE_ANONYMOUS”授權,因此可以使用它來進行訪問控制。例如,如果按照以下方式設置,則只有未經驗證的用戶才能訪問”/anon”。參考資料:https://www.tenohira.xyz/tech/spring-anonymous-only-access/

@Configuration
@EnableWebSecurity
public class SecurityConfig {
  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.formLogin(login -> login
        // 省略
    ).authorizeHttpRequests(authz -> authz
        .requestMatchers("/anon").anonymous()
        //.requestMatchers("/anon").hasRole("ANONYMOUS") // 上と同じ意味
        .anyRequest().authenticated()
    );
    return http.build();
  }

在thymeleaf中根据是否为匿名来进行某些显示切换的方法如下所示。有关更详细的用法,请参考https://kagamihoge.hatenablog.com/entry/2019/11/12/195357。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="https://www.thymeleaf.org"
  xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>anonymous sample</title>
</head>
<body>
		<div sec:authorize="isAnonymous()">
		  ANONYMOUSです。
		</div>
		<div sec:authorize="hasRole('ANONYMOUS')">
		  ANONYMOUSです。
		</div>
</body>
</html>

对于更改anonymous的授权认可,默认的ROLE_ANONYMOUS,更改主要的principal,或者禁用anonymous认证,可以进行以下操作。

  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http. 
     // 省略
    ).anonymous((anon) -> anon
        .authorities("ROLE_HOGE", "ROLE_FOO")
        .principal("アノニマス")
        // .disable() // 無効化
    );
广告
将在 10 秒后关闭
bannerAds