Spring Security 5 / Login / REST API Accessibility / Bad Credentials即使它们是正确的?

时间:2018-04-14 13:11:10

标签: java rest authentication spring-boot spring-security

我正在使用Spring Boot(2.0.1)实现REST API以与MongoDB(3.6)一起使用。我真的卡住了。我还尝试过StackOverFlow的其他提示,但由于某些原因它没有帮助。

我已经将SecurityConfig.java配置为允许访问某些区域,并且还创建了一个用户inMemoryAuthentication,以便能够登录到HAL Browser(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;
//    }

}

我已经尝试了不同的方法(注释块),但仍然没有运气。 即使permitAll()上有/register,我仍然会收到自动生成的登录表单,该表单不会接受任何凭据。

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

有什么方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

从我所看到的情况来看,你的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注释(例如@Configuration),则Spring Boot不会检测类中的注释。 ,@Service,...)

编辑:我很快就制定了一个程序来模仿你的情况:

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和任何密码(记住,假密码编码器不关心密码)登录时,它会将我重定向到{{ 1}}并显示以下内容:

/

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

相关问题