繁体   English   中英

Spring Security 5 /登录/ REST API可访问性/错误的凭证,即使它们是正确的?

[英]Spring Security 5 / Login / REST API Accessibility / Bad Credentials even if they are right?

我正在使用Spring Boot(2.0.1)实现MongoDB(3.6)的REST API。 我真的被卡住了。 我也尝试了StackOverFlow的其他技巧,但由于某些原因没有帮助。

我已经配置了SecurityConfig.java以允许访问某些区域,并且还创建了一个用户inMemoryAuthentication,以便能够登录到HAL浏览器(Spring)等。但是问题是,无论我在浏览器中输入的任何地址都得到了由于某种原因,登录表单和inMemoryAuthentication中使用的凭据总是错误的。 我发现访问API的唯一方法是在主类中排除SecurityAutoConfiguration。 但这会打开所有权限,无需身份验证即可访问包括HAL浏览器在内的所有内容。

有人会告诉我我做错了吗? 我只想允许所有人使用某些路径/地址,只允许将其他所有内容与TokenAuthentication一起使用(已经对其进行了自定义实现),并且只有一个用户(用户名,密码)访问HAL浏览器。

这是我的SecurityConfig.java:

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Autowired
    private final TokenAuthenticationService tokenAuthenticationService;

    @Autowired
    protected SecurityConfig(final TokenAuthenticationService tokenAuthenticationService) {
        super();
        this.tokenAuthenticationService = tokenAuthenticationService;
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.csrf().disable()
                .addFilterBefore(new TokenAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers("/hello").permitAll()
                .antMatchers("/test2").permitAll()
                .antMatchers("/register").permitAll()
                .antMatchers("/useraccount").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().permitAll()
                .and()
                .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//      auth
//              .inMemoryAuthentication()
//              .withUser("user1").password("password").roles("ADMIN");
        auth
                .inMemoryAuthentication()
                .withUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER"));
//      auth
//              .userDetailsService(userService);
    }

//    @Bean
//    @Override
//    public UserDetailsService userDetailsService() {
//        UserDetails user =
//                User.withDefaultPasswordEncoder()
//                        .username("user")
//                        .password("password")
//                        .roles("USER")
//                        .build();
//
//        return new InMemoryUserDetailsManager(user);
//    }

//    @Bean
//    public UserDetailsService userDetailsService() {
//        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
//        manager.createUser(User.withUsername("user").password("pass").roles("USER", "ADMIN").build());
//        return manager;
//    }

}

如您所见,我尝试了不同的方法(注释块),但是仍然没有运气。 即使我在/register上具有permitAll() ,我仍然会获得自动生成的登录表单,该表单将不接受任何凭据。

因此,正如我之前所说,使用我的API的唯一方法是排除SecurityAutoConfiguration( @EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class ),但这不是安全的选择。

有什么办法解决这个问题?

据我所知,您的SecurityConfig类很可能从未调用,因为它没有任何注释指示Spring Boot应该在类中寻找要自动装配的bean( @Autowired

为了给您一个主意,以下内容将永远不会被调用:

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        System.out.println("This will never called");
    }

}

而如果我们有@EnableWebSecurity

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        System.out.println("This is called");
    }

}

请记住,如果类本身未使用@Component或继承了@Component注释的其他注释(例如@Service @Configuration@Service @Component ,...)进行注释,则Spring Boot将不会在类内部检测到注释。


编辑 :我迅速建立了一个程序来模仿您的情况:

SecurityConfiguration.java

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser(new User("root", "root", Arrays.asList(new SimpleGrantedAuthority("USER"))))
                .passwordEncoder(fakePasswordEncoder());
    }


    @Bean
    public PasswordEncoder fakePasswordEncoder() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return null; // matches(...) will always return true anyways
            }

            @Override
            public boolean matches(CharSequence charSequence, String s) {
                return true;
            }
        };
    }


    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/hello").permitAll()
            .antMatchers("/test2").permitAll()
            .antMatchers("/register").permitAll()
            .antMatchers("/useraccount").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().permitAll()
            .and()
            .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll();
    }

}

请注意,我只是快速制作了一个忽略密码的密码编码器,因为这将需要更多的工作

ExampleController.java

@RestController
public class ExampleController {

    @GetMapping("/")
    public Object index() {
        return getCurrentUser();
    }


    public Object getCurrentUser() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        return ((UsernamePasswordAuthenticationToken)auth).getPrincipal();
    }

}

当我使用用户名root和任何密码登录时( 记住,假密码编码器并不关心密码 ),它会将我重定向到/并显示以下内容:

{"password":null,"username":"root","authorities":[{"authority":"USER"}],"accountNonExpired":true,"accountNonLocked":true,"credentialsNonExpired":true,"enabled":true}

(这是正常的,因为这就是我要输出的内容)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM