Spring Boot / Spring Security,登录表单,用户名无关

时间:2018-07-20 21:33:38

标签: java spring-boot spring-security

我已经编写了一个APP,该APP到目前为止已经实现了登录表单。

我使用Spring-Boot 2.x,Java 9和Security ofc。

我的测试表明,用户在登录表单中输入的用户名实际上并不重要,只要用户密码正确,每个用户名都会被接受。

这让我非常困惑。

我希望这里有人可以提供帮助。如果您还有其他建议可以改善我的代码,请告诉我。

安全配置

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsServiceImpl userDetailsService;

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        return bCryptPasswordEncoder;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        // Setting Service to find User in the database.
        // And Setting PassswordEncoder
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // disable Cross Site Request Forgery
        http.csrf().disable();

        // The pages does not require login
        http.authorizeRequests()
                .antMatchers("/", "/login", "/register")
                .permitAll();

        // userInfo page requires login as ROLE_USER or ROLE_ADMIN.
        // If no login, it will redirect to /login page.
        // TODO ask if I really have to add every route here manually
        http.authorizeRequests()
                .antMatchers("/selectGet", "/success")
                .access("hasAnyRole('ROLE_ADMIN')");

        // When the user is not admin
        // But access a page that requires admin role,
        // AccessDeniedException will be thrown.
        http.authorizeRequests()
                .and()
                .exceptionHandling()
                .accessDeniedPage("/403");

        // Config for Login Form
        http.authorizeRequests().and().formLogin()//
                // Submit URL of login page.
                .loginProcessingUrl("/j_spring_security_check") // Submit URL
                .loginPage("/login")//
                .defaultSuccessUrl("/success")//
                .failureUrl("/login?error=true")//
                .usernameParameter("username")//
                .passwordParameter("password")
                // Config for Logout Page
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/logoutSuccessful");
    }
}

UserDetailsS​​erviceImpl

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    UserRepo userRepo;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        if (userRepo.count() < 1) {
            System.out.println("SpringUser not found! " + userName);
            throw new UsernameNotFoundException("SpringUser " + userName + " was not found in the database");
        }
        return userRepo.findAll().iterator().next();
    }
}

用户

@Entity
@EqualsAndHashCode
public class SpringUser implements UserDetails {

    // TODO https://spring.io/guides/gs/validating-form-input/
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    /*  @NotNull
      @Size(min = 2, max = 30)*/
    private String username;

    /*    @NotNull
        @Size(min = 4, max = 30)*/
    private String password;

    public SpringUser() {
    }

    public SpringUser(final String username, final String password) {
        this.username = username;
        this.password = EncrytedPasswordUtils.encrytePassword(password);
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> grantList = new ArrayList<>();
        grantList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        return grantList;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

控制器中的相关方法

@PostMapping("/register")
public String registerPost(@RequestParam("username") String username,
                           @RequestParam("password") String password) {
    System.out.println("post Register");
    SpringUser springUser = new SpringUser(username, password);
    userRepo.save(springUser);
    return "redirect:";
}

注册html

  <form method="post" th:action="@{/register}" >
                <input type="text" id="login" class="fadeIn second" name="username" placeholder="username" maxlength="10">
                <input type="text" id="password" class="fadeIn third" name="password" placeholder="password">
                <input type="submit" class="fadeIn fourth" value="Register">
            </form>

登录html

                                                        

1 个答案:

答案 0 :(得分:1)

您的问题在这里:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    UserRepo userRepo;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        if (userRepo.count() < 1) {
            System.out.println("SpringUser not found! " + userName);
            throw new UsernameNotFoundException("SpringUser " + userName + " was not found in the database");
        }
        return userRepo.findAll().iterator().next();
    }
}

JavaDoc

  

根据用户名定位用户。在实际的实现中,搜索可能区分大小写,或者不区分大小写,具体取决于实现实例的配置方式。在这种情况下,返回的UserDetails对象的用户名可能与实际请求的用户名不同。

强调地雷

因此,您应该按用户名找到UserDetails。您的代码将忽略userName并执行以下操作:

userRepo.findAll().iterator().next();

即您只需抓住所有用户,然后选择第一个并返回。

您的代码应执行以下操作:

userRepo.findByUsername(userName);

您需要确定UserDetails中是否有UserRepo的{​​{1}}与表单上提交的用户名相匹配。


TL; DR:用户名将被忽略,因为您忽略了用户名。