簡體   English   中英

春季安全性:AnonymousAuthenticationToken與UsernamePasswordAuthenticationToken

[英]Spring Security: AnonymousAuthenticationToken vs UsernamePasswordAuthenticationToken

我正在研究Gradle / Java 1.8 / Spring Boot,Spring Integration,Spring Batch,Spring Data Rest項目(我繼承了)。

這是來自以下版本的依賴項:build.gradle

// Spring Boot
compile("org.springframework.boot:spring-boot-starter-ws")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-integration")
compile("org.springframework.boot:spring-boot-starter-actuator")
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.springframework.boot:spring-boot-starter-batch")

// Spring integration
compile("org.springframework.integration:spring-integration-core")
compile("org.springframework.integration:spring-integration-ws")
compile("org.springframework.integration:spring-integration-jpa")
compile("org.springframework.integration:spring-integration-sftp")

// Spring batch
compile("org.springframework.batch:spring-batch-core")
compile("org.springframework.batch:spring-batch-integration")

// Spring Data REST
compile("org.springframework.data:spring-data-rest-webmvc")

查看應用程序的DEBUG日志,我看到兩個線程:

i. [http-nio-8080-exec-1],
ii [[http-nio-8080-exec-2]

第一個調用AnonymousAuthenticationToken並在@ 15:02:56.731中失敗:

org.springframework.security.authentication.AnonymousAuthenticationToken

幾毫秒后@ 15:02:56.747第二個成功執行:org.springframework.security.authentication.UsernamePasswordAuthenticationToken

例如

15:02:56.731 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
15:02:56.747 [http-nio-8080-exec-2] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fb774aa3: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER

15:02:56.731 [http-nio-8080-exec-1] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@9324be9, returned: -1
15:02:56.747 [http-nio-8080-exec-2] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@9324be9, returned: 1

15:02:56.731 [http-nio-8080-exec-1] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.integration.internalMessagingAnnotationPostProcessor'
15:02:56.747 [http-nio-8080-exec-2] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful

失敗的方法:AnonymousAuthenticationToken生成異常。

來自application.yml的代碼段:

# Authentication for "user" to the HTTP endpoints
security:
  user:
    password: blahblahblah
  1. Spring book是否首先嘗試使用AnonymousAuthenticationToken代碼,因為application.yml中的“用戶”字段為空?

  2. 當我將'user'字段更改為真實值時,我的gradle構建在sftp驗證中出現錯誤:

11:57:25.869 [DEBUG] [TestEventLogger]原因:11:57:25.869 [DEBUG] [TestEventLogger]此處不允許使用映射值11:57:25.869 [DEBUG] [TestEventLogger]在“ reader”行33中,列13:11:57:25.880 [DEBUG] [TestEventLogger]密碼:blahblahblah 11:57:24.166 [DEBUG] [TestEventLogger]位於org.yaml.snakeyaml.scanner.ScannerImpl.fetchValue(ScannerImpl.java:871)11:57 :24.167 [DEBUG] [TestEventLogger],位於org.yaml.snakeyaml.scanner.ScannerImpl.fetchMoreTokens(ScannerImpl.java:360)11:57:24.167 [DEBUG] [TestEventLogger],位於org.yaml.snakeyaml.scanner.ScannerImpl.checkToken (ScannerImpl.java:226)11:57:24.167 [DEBUG] [TestEventLogger]在org.yaml.snakeyaml.parser.ParserImpl $ ParseBlockMappingKey.produce(ParserImpl.java:558)11:57:24.168 [DEBUG] [TestEventLogger]在org.yaml.snakeyaml.parser.ParserImpl.checkEvent(ParserImpl.java:143)11:57:24.168 [DEBUG] [TestEventLogger]在org.yaml.snakeyaml.parser.ParserImpl.checkEvent(ParserImpl.java:143)11 :57:24.169 [DEBUG] [TestEventLogger]在或 g.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:226)11:57:24.169 [DEBUG] [TestEventLogger]位於org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:155)11: 57:24.169 [調試] [TestEventLogger]位於org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:231)11:57:24.171 [調試] [TestEventLogger]位於org.yaml.snakeyaml.composer.Composer。 composeNode(Composer.java:155)11:57:24.171 [DEBUG] [TestEventLogger]位於org.yaml.snakeyaml.composer.Composer.composeDocument(Composer.java:122)11:57:24.175 [DEBUG] [TestEventLogger]位於org.yaml.snakeyaml.constructor.BaseConstructor.getData(BaseConstructor.java:104)上的org.yaml.snakeyaml.composer.Composer.getNode(Composer.java:84)11:57:24.176 [DEBUG] [TestEventLogger] 11: 57:24.176 [DEBUG] [TestEventLogger]在org.yaml.snakeyaml.Yaml $ 1.next(Yaml.java:502)11:57:24.176 [DEBUG] [TestEventLogger]在org.springframework.beans.factory.config.YamlProcessor .process(YamlProcessor.java:160)11:57:24.176 [DEBUG] [TestEvent 記錄器],位於org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:138)11:57:24.176 [DEBUG] [TestEventLogger],位於org.springframework.boot.env.YamlPropertySourceLoader $ Processor.process(YamlPropertySourceLoader .java:100)11:57:24.181 [調試] [TestEventLogger]在org.springframework.boot.env.YamlPropertySourceLoader.load(YamlPropertySourceLoader.java:57)11:57:24.183 [QUIET] [system.out] 11: 57:24.183 [DEBUG] [org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor]執行測試類com.distributedfinance.mbi.payment.repository.ExternalAccountTransferRepositorySpecIT 11:57:24.184 [DEBUG] [TestEventLogger]在org .springframework.boot.env.PropertySourcesLoader.load(PropertySourcesLoader.java:126)11:57:24.184 [DEBUG] [TestEventLogger]位於org.springframework.boot.context.config.ConfigFileApplicationListener $ Loader.loadIntoGroup(ConfigFileApplicationListener.java:381 )11:57:24.184 [調試] [TestEventLogger]位於org.springframework.boot.context.config.C onfigFileApplicationListener $ Loader.load(ConfigFileApplicationListener.java:369)11:57:24.184在org.springframework.boot.context.config.ConfigFileApplicationListener $ Loader.load(ConfigFileApplicationListener.java:339)11:57處的[DEBUG] [TestEventLogger]: org.springframework.boot.context.config.ConfigFileApplicationListener.addPropertySources(ConfigFileApplicationListener.java:174)上的24.184 [DEBUG] [TestEventLogger] 11:57:24.185 org.springframework.boot.context.config上的[DEBUG] [TestEventLogger]。 ConfigFileApplicationListener.onApplicationEnvironmentPreparedEvent(ConfigFileApplicationListener.java:144)11:57:24.185 [DEBUG] [TestEventLogger]位於org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEnvironmentPreparedEvent(ConfigFileApplicationListener.java:137)11:57:24.185 [DEBUG] org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEvent(ConfigFileApplicationListener.java:126)上的[TestEventLogger] 11:57:24.185 [DEBUG] [TestEventLo gger]在org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)11:57:24.185 [DEBUG] [TestEventLogger]在org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128 )11:57:24.186 [調試] [TestEventLogger]在org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:100)11:57:24.186 [調試] [TestEventLogger]在org.springframework.boot .context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:59)11:57:24.186 [DEBUG] [TestEventLogger]在org.springframework.boot.SpringApplication.run(SpringApplication.java:285)11:57:24.186 [DEBUG ] [TestEventLogger]在org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:103)11:57:24.186 [DEBUG] [TestEventLogger]在org.springframework.test.context.DefaultCacheAwareContextL oaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68)11:57:24.187 [DEBUG] [TestEventLogger]在org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86)11:57:24.187 [Event] ] ...另外24個

  1. 為什么是應用程序。 配置為嘗試兩種身份驗證方法?
  2. 應該如何配置?
  3. Spring Boot自動配置中是否有某些東西可以控制這一點?

在此處輸入圖片說明

絕對錯誤是在UsernamePasswordAuthenticationFilter之前執行AnonymousAuthenticationFilter(在此處檢查默認順序)

我欠您有關為何在您的情況下如此配置的解釋,但我會回答這一問題。

  1. 為什么是應用程序。 配置為嘗試兩種身份驗證方法?

匿名篩選器必須在進行任何身份驗證嘗試后執行,並且如果沒有身份驗證器,它將執行一個AuthenticationToken到SecurityContextHolder中(這意味着所有身份驗證嘗試均失敗)。

Spring這樣做是為了以更一致的方式處理Authentication令牌,否則應詢問SecurityContextHolder.getAuthentication!= null,這會使授權機制復雜化,例如詢問用戶角色。

從Spring 文檔

請注意,“匿名身份驗證”的用戶與未經身份驗證的用戶之間沒有真正的概念差異。 Spring Security的匿名身份驗證只是為您提供了一種更方便的方式來配置訪問控制屬性。 即使在SecurityContextHolder中實際上存在一個匿名身份驗證對象,對諸如getCallerPrincipal之類的Servlet API調用的調用仍將返回null。

如果類知道SecurityContextHolder始終包含Authentication對象並且從不為null,則可以更強大地編寫類。

發生的情況是,您正在向不需要身份驗證的端點發出請求,但是您在請求中包含憑據。

  1. 請求到/ securedEndpoint的憑據,但沒有授權標頭
  2. BasicAuthenticationFilter已執行,但是沒有Authorization標頭,因此無法驗證用戶身份。
  3. 將執行AnonymousAuthenticationFilter,並將AnonymousToken放入SecurityContextHolder中。
  4. 授權機制拋出異常,因為請求嘗試獲取安全資源。
  5. ExceptionTranslationFilter捕獲此異常並調用AuthenticationEntryPoint
  6. AuthenticationEntryPoint重定向到/ login
  7. UsernamePassordAuthenticationFilter將被執行並成功驗證您的用戶。
  8. 再次執行AnonymousAuthenticationFilter,但是就像SecurityContextHolder alredy中有一個Authentication一樣,它什么也不做。
  9. 授權機制允許用戶獲取資源。

如果您需要無狀態/無會話的后端,並且要隨每個請求發送憑據,則必須將UsernamePasswordAuthenticationFilter配置為在所有請求(/ )或所有安全端點(/ secure / )中執行。 基本身份驗證過濾器不是必需的,但您可以使用過濾器。

提示:可以使用JWT進行無狀態身份驗證。

更新:

用於在Spring Boot中自定義安全配置

默認的安全配置在SecurityAutoConfiguration以及從那里導入的類中實現(用於Web安全的SpringBootWebSecurityConfiguration和用於身份驗證配置的AuthenticationManagerConfiguration,這也與非Web應用程序相關)。 要完全關閉Web應用程序中的Boot默認配置,可以使用@EnableWebSecurity添加bean。 要對其進行自定義,通常使用外部屬性和WebSecurityConfigurerAdapter類型的Bean(例如,添加基於表單的登錄名) Spring Boot 示例中有幾個安全應用程序,可以幫助您開始使用常見的用例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM