gpt4 book ai didi

java - Spring 安全 : AnonymousAuthenticationToken vs UsernamePasswordAuthenticationToken

转载 作者:行者123 更新时间:2023-11-30 06:11:58 24 4
gpt4 key购买 nike

我正在研究 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 Boot 是否先尝试 AnonymousAuthenticationToken 代码,因为application.yml 中的“用户”字段为空?

  2. 当我将“用户”字段更改为实际值时,我的 gradle 构建在 sftp 验证中出现错误:

11:57:25.869 [DEBUG] [TestEventLogger] Caused by: 11:57:25.869 [DEBUG] [TestEventLogger] mapping values are not allowed here 11:57:25.869 [DEBUG] [TestEventLogger] in 'reader', line 33, column 13: 11:57:25.880 [DEBUG] [TestEventLogger] password: blahblahblah 11:57:24.166 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.scanner.ScannerImpl.fetchValue(ScannerImpl.java:871) 11:57:24.167 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.scanner.ScannerImpl.fetchMoreTokens(ScannerImpl.java:360) 11:57:24.167 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.scanner.ScannerImpl.checkToken(ScannerImpl.java:226) 11:57:24.167 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.parser.ParserImpl$ParseBlockMappingKey.produce(ParserImpl.java:558) 11:57:24.168 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.parser.ParserImpl.peekEvent(ParserImpl.java:158) 11:57:24.168 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.parser.ParserImpl.checkEvent(ParserImpl.java:143) 11:57:24.169 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:226) 11:57:24.169 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:155) 11:57:24.169 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:231) 11:57:24.171 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:155) 11:57:24.171 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.composer.Composer.composeDocument(Composer.java:122) 11:57:24.175 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.composer.Composer.getNode(Composer.java:84) 11:57:24.176 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.constructor.BaseConstructor.getData(BaseConstructor.java:104) 11:57:24.176 [DEBUG] [TestEventLogger] at org.yaml.snakeyaml.Yaml$1.next(Yaml.java:502) 11:57:24.176 [DEBUG] [TestEventLogger] at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:160) 11:57:24.176 [DEBUG] [TestEventLogger] at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:138) 11:57:24.176 [DEBUG] [TestEventLogger] at org.springframework.boot.env.YamlPropertySourceLoader$Processor.process(YamlPropertySourceLoader.java:100) 11:57:24.181 [DEBUG] [TestEventLogger] at 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] Executing test class com.distributedfinance.mbi.payment.repository.ExternalAccountTransferRepositorySpecIT 11:57:24.184 [DEBUG] [TestEventLogger] at org.springframework.boot.env.PropertySourcesLoader.load(PropertySourcesLoader.java:126) 11:57:24.184 [DEBUG] [TestEventLogger] at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.loadIntoGroup(ConfigFileApplicationListener.java:381) 11:57:24.184 [DEBUG] [TestEventLogger] at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:369) 11:57:24.184 [DEBUG] [TestEventLogger] at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:339) 11:57:24.184 [DEBUG] [TestEventLogger] at org.springframework.boot.context.config.ConfigFileApplicationListener.addPropertySources(ConfigFileApplicationListener.java:174) 11:57:24.185 [DEBUG] [TestEventLogger] at org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEnvironmentPreparedEvent(ConfigFileApplicationListener.java:144) 11:57:24.185 [DEBUG] [TestEventLogger] at org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEnvironmentPreparedEvent(ConfigFileApplicationListener.java:137) 11:57:24.185 [DEBUG] [TestEventLogger] at org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEvent(ConfigFileApplicationListener.java:126) 11:57:24.185 [DEBUG] [TestEventLogger] at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151) 11:57:24.185 [DEBUG] [TestEventLogger] at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128) 11:57:24.186 [DEBUG] [TestEventLogger] at org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:100) 11:57:24.186 [DEBUG] [TestEventLogger] at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:59) 11:57:24.186 [DEBUG] [TestEventLogger] at org.springframework.boot.SpringApplication.run(SpringApplication.java:285) 11:57:24.186 [DEBUG] [TestEventLogger] at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:103) 11:57:24.186 [DEBUG] [TestEventLogger] at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68) 11:57:24.187 [DEBUG] [TestEventLogger] at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86) 11:57:24.187 [DEBUG] [TestEventLogger] ... 24 more

  1. 为什么是应用程序。配置为尝试两种身份验证方法?
  2. 应该如何配置?
  3. Spring Boot 自动配置中有什么东西可以控制它吗?

enter image description here

最佳答案

绝对错误是 AnonymousAuthenticationFilter 在 UsernamePasswordAuthenticationFilter 之前执行(检查默认顺序 here )

我欠你解释为什么你的情况是这样配置的,但我会回答这个问题。

  1. Why is the app. configured to try both methods of authentication?

匿名过滤器必须在任何身份验证尝试之后执行,它所做的是将 AuthenticationToken 放入 SecurityContextHolder 中(如果还没有)(这意味着所有身份验证尝试都失败了)。

Spring 这样做是为了以更一致的方式处理身份验证 token ,否则它应该询问是否 SecurityContextHolder.getAuthentication != null 这将使授权机制复杂化,例如询问用户的角色。

从 Spring 开始documentation :

Note that there is no real conceptual difference between a user who is “anonymously authenticated” and an unauthenticated user. Spring Security's anonymous authentication just gives you a more convenient way to configure your access-control attributes. Calls to servlet API calls such as getCallerPrincipal, for example, will still return null even though there is actually an anonymous authentication object in the SecurityContextHolder.

Classes can be authored more robustly if they know the SecurityContextHolder always contains an Authentication object, and never null.

发生的情况是,您正在向需要身份验证但未经过身份验证的端点发出请求,但您在请求中包含了您的凭据。

  1. 使用凭证请求/securedEndpoint 但没有授权 header
  2. BasicAuthenticationFilter 已执行,但没有授权 header ,因此无法对用户进行身份验证。
  3. 执行 AnonymousAuthenticationFilter 并将 AnonymousToken 放入 SecurityContextHolder。
  4. 授权机制抛出异常,因为请求试图获取 protected 资源。
  5. ExceptionTranslationFilter 捕获此异常并调用 AuthenticationEntryPoint
  6. AuthenticationEntryPoint 重定向到/login
  7. 执行 UsernamePassordAuthenticationFilter 并成功验证您的用户。
  8. AnonymousAuthenticationFilter 被再次执行,但就像 SecurityContextHolder 中已经有一个 Authentication 一样,它什么也没做。
  9. 授权机制允许用户获取资源。

如果你想要一个无状态/无 session 的后端,并且你打算在每个请求中发送你的凭据,你必须配置你的 UsernamePasswordAuthenticationFilter 以在所有请求(/)或所有安全端点(/secure/). BasicAuthenticationFilter 不是必需的,但您可以使用过滤器。

提示:您可以使用 JWT 进行无状态身份验证。

更新:

用于在 Spring boot 中自定义您的安全配置

The default security configuration is implemented in SecurityAutoConfiguration and in the classes imported from there (SpringBootWebSecurityConfiguration for web security and AuthenticationManagerConfiguration for authentication configuration which is also relevant in non-web applications). To switch off the Boot default configuration completely in a web application you can add a bean with @EnableWebSecurity. To customize it you normally use external properties and beans of type WebSecurityConfigurerAdapter (e.g. to add form-based login). There are several secure applications in the Spring Boot samples to get you started with common use cases.

关于java - Spring 安全 : AnonymousAuthenticationToken vs UsernamePasswordAuthenticationToken,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33410763/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com