当前位置: 首页 > 知识库问答 >
问题:

NoOpPasswordEncoder不工作,返回状态码200而不是401

呼延升
2023-03-14

我试图通过spring boot学习Spring Security的基础知识,我创建了一个项目,其中还包括postgresql设置。Postgresql部分按预期工作。

问题是,在我通过正确的凭据访问安全endpoint后,我只是试图使用正确的用户名和错误的密码进行访问,并期待401错误,但返回200。并返回endpoint的内容。

  • 如果我使用用户名:dummy_user密码:12345进行基本身份验证请求,则响应为401 UnAuthorized
  • 如果我使用用户名:dummy_user密码:1234进行基本身份验证请求,响应为200
  • 如果我使用用户名:dummy_user密码:1234进行基本身份验证请求,响应为200
  • 响应200后,如果我使用用户名:dummy_user密码:12345进行基本身份验证请求,响应为200

在运行项目之前,我刚刚添加了一个虚拟用户:

INSERT INTO test_users (username,password) VALUES ('dummy_user','1234');

DTO很简单:

@Entity
@Table(name = "test_users")
public class UserDTO {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "username")
    private String username;

    @Column(name = "password")
    private String password;
  • 配置类:
@Configuration
public class ProjectBeanConfiguration {
    @Bean
    public UserDetailsService userDetailsService(){
       return new PostgresqlUserDetailsService();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }
}
  • 和用户详细信息服务:
public class PostgresqlUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username){
        Optional<UserDTO> userDTOOptional = userRepository.findUserByUsername(username);
        UserDTO userInDb = userDTOOptional.orElseThrow(() -> new UsernameNotFoundException("Not Found in DB"));
        SecureUser secureUser = new SecureUser(userInDb);
        return secureUser;
    }
}
  • SecureUser什么都不是,只是将UserDTO映射到UserDetails:
java prettyprint-override">public class SecureUser  implements UserDetails {

    private final UserDTO userDTO;

    public SecureUser(UserDTO userDTO) {
        this.userDTO = userDTO;
    } 
    // ...
    @Override
    public String getPassword() {
        return userDTO.getPassword();
    }

    @Override
    public String getUsername() {
        return userDTO.getUsername();
    }
    // ...
  • 只有一个控制器:
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}
  • Logs for:后响应200,如果我做一个基本的身份验证请求用户名:dummy_user和密码:12345,响应是200:
020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 1 of 15 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 2 of 15 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@8e885cc7: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@8e885cc7: Principal: com...springsecurity.services.SecureUser@49860e95; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: com...springsecurity.services.SecureUser$$Lambda$890/0x0000000800848040@38f11ef2'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 3 of 15 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 4 of 15 in additional filter chain; firing Filter: 'CsrfFilter'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 5 of 15 in additional filter chain; firing Filter: 'LogoutFilter'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /hello' doesn't match 'POST /logout'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 6 of 15 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /hello' doesn't match 'POST /login'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 7 of 15 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 8 of 15 in additional filter chain; firing Filter: 'DefaultLogoutPageGeneratingFilter'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/hello'; against '/logout'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 9 of 15 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.a.www.BasicAuthenticationFilter  : Basic Authentication Authorization header found for user 'dummy_user'
2020-12-27 21:52:19.711 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 10 of 15 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.s.HttpSessionRequestCache        : saved request doesn't match
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 11 of 15 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 12 of 15 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter  : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@8e885cc7: Principal: com...springsecurity.services.SecureUser@49860e95; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: com...springsecurity.services.SecureUser$$Lambda$890/0x0000000800848040@38f11ef2'
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 13 of 15 in additional filter chain; firing Filter: 'SessionManagementFilter'
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 14 of 15 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello at position 15 of 15 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /hello; Attributes: [authenticated]
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@8e885cc7: Principal: com...springsecurity.services.SecureUser@49860e95; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: com...springsecurity.services.SecureUser$$Lambda$890/0x0000000800848040@38f11ef2
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@5b81c050, returned: 1
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorization successful
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : RunAsManager did not change Authentication object
2020-12-27 21:52:19.712 DEBUG 32988 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /hello reached end of additional filter chain; proceeding with original chain
2020-12-27 21:52:19.714 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@70616cef
2020-12-27 21:52:19.715 DEBUG 32988 --- [nio-8080-exec-2] o.s.s.w.a.ExceptionTranslationFilter     : Chain processed normally
2020-12-27 21:52:19.716 DEBUG 32988 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

共有2个答案

戴高远
2023-03-14

您第一次使用正确的用户名和密码登录Spring Security将创建一个会话对象并为您提供一个会话cookie。会话对象是存储信息的对象。当您第一次登录时,它会创建一个身份验证令牌,表示您已成功登录,并将其存储在会话对象中。每次您访问Web应用程序上的安全endpoint时,您都会发送会话cookie。cookie将您标识为已被登录。要删除会话cookie,请转到注销终端url,这将删除您的会话。

诸葛皓
2023-03-14

根据日志:

SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@8e885cc7: Principal

这表明当您访问hello时,上下文中已经有一个主体。

然后日志告诉我们:

Previously Authenticated

所以我的结论(因为这不是完整的日志),我们还没有看到您是如何完成您的请求的,如下所示:

// No session established, you provide wrong credentials, you get a 401
 - If I do a basic authentication request with username: dummy_user and password: 12345, response is 401 UnAuthorized

// You authenticate correctly, we establish a session, you get a session cookie
- If I do a basic authentication request with username: dummy_user and password: 1234, response is 200

// You provide the session cookie in your request, we get a 200OK
- If I do a basic authentication request with username: dummy_user and password: 1234, response is 200

// You still provide the session cookie, we get a 200OK 
- After response 200, If I do a basic authentication request with username: dummy_user and password: 12345, response is 200

如果你想确认这个理论,你应该在每次登录尝试之间/logout,或者删除设置好的cookie。

 类似资料:
  • 我有一个名为Backend(端口:9090)的服务,位于Zuul(端口:8080)后面。 浏览器在Zuul上调用GET方法,执行重定向。 示例调用:http://localhost:8080/testredirect 结果: 浏览器收到Http状态=200 浏览器URL:http://localhost:8080/testredirect 浏览器显示:Hello world 预期结果: 浏览器应接

  • 问题内容: 我有一台服务器,从同一URL返回HTTP状态代码200、201和202。在Chrome浏览器中,我已经通过“网络”调试面板确认了状态代码是否符合我的预期(即200、201或202)。我依靠该状态码来确定下一步。 我希望jQuery(1.5.2版)AJAX的回调请求设置为服务器发送的状态代码。但是,即使服务器发送的代码是201或202,状态代码也始终为200。 换句话说,无论服务器发送什

  • 我正在做一个新项目,我想实现一个“等到网站打开”功能,如果http://switch-check.cf/index.php打开,然后继续。 现在,在我的帮助下。htaccess和php我尽了最大的努力。禁止访问php文件。因此,如果你试图访问我提到的网页,你应该得到一个 403拒绝访问 因此,我使用urllib(也尝试了请求)查看网站是否已打开或仍处于禁止访问状态然而,无论我尝试什么,我总是得到2

  • 我已经在我的AEM服务器上配置了ETag(使用ACS Commons ETag支持),并在Apache上禁用了ETag。但是一旦文件被缓存在调度程序上,Apache总是返回200和响应体,而不是304没有修改。我已经验证了ETag值存储在。h”文件,并且在响应中与请求的“如果不匹配”报头的值相同。如果我从调度程序中删除缓存的文件并重新发送请求,那么AEM会正确地返回304。 我还禁用了mod_de

  • 编辑问题以包括所需的行为、特定问题或错误,以及重现问题所需的最短代码。这将有助于其他人回答这个问题。 代码不返回值,而是返回“?”。编译时我没有遇到任何错误。请协助。 代码需要返回需要支付的剩余金额。输出代码1代码2代码3代码4

  • 问题内容: 这是一个非常简单的测试,但我似乎无法正确完成。 我想检查哪些用户可以登录并执行操作(这是一整套测试的一部分),但是第一步会引起一些问题。 当我运行测试时,我得到: 为什么我不正确登录时django返回HTTP代码? 对于其他上下文,这是我如何管理登录/注销URL: 问题答案: Web社区中有一些关于对凭证失败的正确响应的辩论。例如,这是有关从切换到的Wordpress凭单。在Stack