Spring启动安全性考虑不区分大小写的用户名检查登录

时间:2017-06-29 09:53:40

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

我正在开发一个Spring启动Web应用程序。问题出在登录方案中。假设我有一个用户名注册的用户" Ali"。该用户可以使用用户名" Ali"或"阿里"。下面的代码代表我的spring安全配置类。在比较时,Spring启动不会检查大写的小写因子,但是我想要检查它。

package ir.saafta.conf;

import ir.saafta.repo.EventRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import javax.sql.DataSource;

/**
 * Created by reza on 11/12/16.
 */
@Configuration
public class SecurityConf extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource datasource;
    @Autowired
    private EventRepository eventRepository;

    // Register HttpSessionEventPublisher
    @Bean
    public static ServletListenerRegistrationBean httpSessionEventPublisher() {
        return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
//                 .antMatchers(HttpMethod.POST, "/users/").permitAll()
                .antMatchers(HttpMethod.GET, "/**").permitAll()
                .antMatchers(HttpMethod.POST, "/**").permitAll()
                .antMatchers(HttpMethod.PUT, "/**").permitAll()
                .antMatchers(HttpMethod.DELETE, "/**").permitAll()
                .antMatchers("/swagger*").permitAll()
                //.anyRequest().permitAll()
                //.and().csrf().disable();
                .anyRequest().authenticated()
                .and().httpBasic()
                .and().formLogin().successHandler(restAuthenticationSuccessHandler()).failureHandler(restAuthenticationFailureHandler())
                .and().logout().logoutSuccessHandler(restLogoutSuccessHandler())
                .and().exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint())
                .and().csrf().disable().cors() //TODO enable csrf when we are ready
                .and().sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true).sessionRegistry(sessionRegistry());
        http.headers().cacheControl().disable()
                .addHeaderWriter(new StaticHeadersWriter("WWW-Authenticate","xBasic realm=\"fake\""));
    }

    @Bean
    public SessionRegistry sessionRegistry() {
        SessionRegistry sessionRegistry = new SessionRegistryImpl();
        return sessionRegistry;
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("*").allowedMethods("PUT", "POST", "GET", "DELETE", "HEAD");
            }
        };
    }

    @SuppressWarnings("SpringJavaAutowiringInspection")
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth, UserDetailsService userDetailsService) throws Exception {
        /*auth
                .jdbcAuthentication().usersByUsernameQuery("Select username,password, 'true' as enabled from Users where username=?")
                .authoritiesByUsernameQuery("select username, authority from authorities where username=?")
                .dataSource(datasource).passwordEncoder(new BCryptPasswordEncoder());*/
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());
    }

    @Bean
    public AuthenticationEntryPoint restAuthenticationEntryPoint() {
        return new RestAuthenticationEntryPoint();
    }

    @Bean
    public AuthenticationFailureHandler restAuthenticationFailureHandler() {
        return new SimpleUrlAuthenticationFailureHandler();
    }

    @Bean
    public AuthenticationSuccessHandler restAuthenticationSuccessHandler() {
        return new RESTAuthenticationSuccessHandler(eventRepository);
    }

    @Bean
    public LogoutSuccessHandler restLogoutSuccessHandler() {
        return new RESTLogoutSuccessHandler(eventRepository);
    }
}

我还在User类中实现了return getattachments()方法:

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;

        User user = (User) o;

        if (!getUsername().equals(user.getUsername())) return false;
        if (getName() != null ? !getName().equals(user.getName()) : user.getName() != null) return false;
        if (getFamily() != null ? !getFamily().equals(user.getFamily()) : user.getFamily() != null) return false;
        if (getPassword() != null ? !getPassword().equals(user.getPassword()) : user.getPassword() != null)
            return false;
        return getMobilePhone() != null ? getMobilePhone().equals(user.getMobilePhone()) : user.getMobilePhone() == null;
    }

2 个答案:

答案 0 :(得分:3)

您可以尝试更改用户名列:

ALTER TABLE USERS MODIFY username VARCHAR(50) BINARY 

答案 1 :(得分:1)

正如@dur在评论中所述,我在我的数据库中检查了这些查询:

checked:boolean = true;
          constructor(public jsonDataService: JsonDataService, public injector: Injector) { }

      search(event, from) {
            if(this.checked){
              alert("checked");
            }
            else{
              alert("unchecked");
            }
            if (this.searchData === "" || this.searchData === null) {
           alert("Enter any keyword to search !");
            }else if(this.checked === true && this.searchData === "" || this.searchData === null ){
              alert("Enter any keyword to search !");
            }else if(this.checked !== true && this.searchData === "" || this.searchData === null){
        alert("Enter any keyword to search !");
            }else if(this.checked === true && (this.searchData !== "" || this.searchData !== null)){
        console.log("checked");
        console.log("Searching.......");
           this.jsonDataService.getFilteredData(this.searchData).subscribe(
                  success => this.buildDataUI1(success),
                  error => this.errorMessage = <any>error);  
            }
            else if(this.checked === false && (this.searchData !== "" || this.searchData !== null)){
              console.log("unchecked");
              console.log("Searching.......");
                 this.jsonDataService.searchData(this.searchData).subscribe(
                    success => this.buildDataUI1(success),
                    error => this.errorMessage = <any>error);      
            } 
        }

他们两人都返回了相同的结果。所以我更改了Select username, password, 'true' as enabled from Users where username = 'Ali' Select username, password, 'true' as enabled from Users where username = 'ali' 表格排序的username列,如下所示(之前的排序规则为user):

utf8_general_ci

现在,列SET FOREIGN_KEY_CHECKS=0; ALTER TABLE `mydb`.`user` CHANGE `username` `username` VARCHAR(50) CHARSET utf8 COLLATE utf8_bin NOT NULL; SET FOREIGN_KEY_CHECKS=1; 将区分大小写。