使用 Spring Security 登录失败

Posted

技术标签:

【中文标题】使用 Spring Security 登录失败【英文标题】:Login failure using Spring Security 【发布时间】:2021-09-22 14:25:06 【问题描述】:

这是我第一次使用 Spring-security,我在尝试与实现一起学习时遇到了很多困难。我正在尝试使用 Spring-security 实现登录和注册功能,其中我的注册功能似乎工作正常,而对于登录,我遇到了困难:

2021-07-14 08:30:51.911  INFO 17152 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2021-07-14 08:30:51.915  INFO 17152 --- [  restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration    : H2 console available at '/h2-console'. Database available at 'jdbc:mysql://localhost:3306/journeyfood?useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC'
2021-07-14 08:30:52.044 DEBUG 17152 --- [  restartedMain] o.s.w.s.r.ResourceUrlEncodingFilter      : Filter 'resourceUrlEncodingFilter' configured for use
2021-07-14 08:30:52.481  INFO 17152 --- [  restartedMain] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2021-07-14 08:30:52.774  INFO 17152 --- [  restartedMain] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.30.Final
2021-07-14 08:30:53.348  INFO 17152 --- [  restartedMain] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations 5.1.2.Final
2021-07-14 08:30:53.719  INFO 17152 --- [  restartedMain] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2021-07-14 08:30:54.979  INFO 17152 --- [  restartedMain] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-07-14 08:30:55.005  INFO 17152 --- [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-07-14 08:30:55.671  WARN 17152 --- [  restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-07-14 08:30:56.069  INFO 17152 --- [  restartedMain] o.s.s.web.DefaultSecurityFilterChain     : Will secure Ant [pattern='/resources/**'] with []
2021-07-14 08:30:56.069  INFO 17152 --- [  restartedMain] o.s.s.web.DefaultSecurityFilterChain     : Will secure Ant [pattern='/static/**'] with []
2021-07-14 08:30:56.095  INFO 17152 --- [  restartedMain] o.s.s.web.DefaultSecurityFilterChain     : Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@44e06dde, org.springframework.security.web.context.SecurityContextPersistenceFilter@5e3ab505, org.springframework.security.web.header.HeaderWriterFilter@77868cf5, org.springframework.security.web.authentication.logout.LogoutFilter@6aead47, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@4419107, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6df74d9c, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@99c0cbf, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2636db06, org.springframework.security.web.session.SessionManagementFilter@6b0130ed, org.springframework.security.web.access.ExceptionTranslationFilter@7af2b0cb, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@53fb5de]
2021-07-14 08:30:56.278  INFO 17152 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-07-14 08:30:56.287 DEBUG 17152 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 1 ResponseBodyAdvice
2021-07-14 08:30:56.366 DEBUG 17152 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : 7 mappings in 'requestMappingHandlerMapping'
2021-07-14 08:30:56.371  INFO 17152 --- [  restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2021-07-14 08:30:56.935 DEBUG 17152 --- [  restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping  : Patterns [/webjars/**, /**] in 'resourceHandlerMapping'
2021-07-14 08:30:56.944 DEBUG 17152 --- [  restartedMain] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice
2021-07-14 08:30:57.217  INFO 17152 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2021-07-14 08:30:57.352  INFO 17152 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path '/JourneyFood'
2021-07-14 08:30:57.365  INFO 17152 --- [  restartedMain] o.b.journeyfood.JourneyFoodApplication   : Started JourneyFoodApplication in 13.587 seconds (JVM running for 17.039)
2021-07-14 08:31:12.439  INFO 17152 --- [nio-8080-exec-1] o.a.c.c.C.[.[localhost].[/JourneyFood]   : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-07-14 08:31:12.440  INFO 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-07-14 08:31:12.440 DEBUG 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected StandardServletMultipartResolver
2021-07-14 08:31:12.440 DEBUG 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected AcceptHeaderLocaleResolver
2021-07-14 08:31:12.440 DEBUG 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected FixedThemeResolver
2021-07-14 08:31:12.441 DEBUG 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@2bed12c2
2021-07-14 08:31:12.441 DEBUG 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.support.SessionFlashMapManager@58fa7aae
2021-07-14 08:31:12.441 DEBUG 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2021-07-14 08:31:12.441  INFO 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2021-07-14 08:31:12.450 DEBUG 17152 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /login
2021-07-14 08:31:12.473 DEBUG 17152 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Secured GET /login
2021-07-14 08:31:12.477 DEBUG 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : GET "/JourneyFood/login", parameters=
2021-07-14 08:31:12.483 DEBUG 17152 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.brahmakumaris.journeyfood.controller.HomeController#login(Model)
2021-07-14 08:31:12.529 DEBUG 17152 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/webp, application/xml;q=0.9, */*;q=0.8]
2021-07-14 08:31:13.021 DEBUG 17152 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2021-07-14 08:31:13.042 DEBUG 17152 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Securing GET /webjars/bootstrap/4.0.0-2/css/bootstrap.min.css
2021-07-14 08:31:13.042 DEBUG 17152 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Securing GET /webjars/bootstrap/4.0.0-2/js/bootstrap.min.js
2021-07-14 08:31:13.042 DEBUG 17152 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Secured GET /webjars/bootstrap/4.0.0-2/js/bootstrap.min.js
2021-07-14 08:31:13.042 DEBUG 17152 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Secured GET /webjars/bootstrap/4.0.0-2/css/bootstrap.min.css
2021-07-14 08:31:13.043 DEBUG 17152 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : GET "/JourneyFood/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js", parameters=
2021-07-14 08:31:13.043 DEBUG 17152 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : GET "/JourneyFood/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css", parameters=
2021-07-14 08:31:13.046 DEBUG 17152 --- [nio-8080-exec-3] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [Classpath [META-INF/resources/webjars/]]
2021-07-14 08:31:13.046 DEBUG 17152 --- [nio-8080-exec-2] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [Classpath [META-INF/resources/webjars/]]
2021-07-14 08:31:13.166 DEBUG 17152 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2021-07-14 08:31:13.168 DEBUG 17152 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2021-07-14 08:31:30.939 DEBUG 17152 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : Securing POST /login
Email: 
2021-07-14 08:31:31.325 DEBUG 17152 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy        : Securing GET /login?error=true
2021-07-14 08:31:31.326 DEBUG 17152 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy        : Secured GET /login?error=true
2021-07-14 08:31:31.327 DEBUG 17152 --- [nio-8080-exec-6] o.s.web.servlet.DispatcherServlet        : GET "/JourneyFood/login?error=true", parameters=masked
2021-07-14 08:31:31.328 DEBUG 17152 --- [nio-8080-exec-6] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.brahmakumaris.journeyfood.controller.HomeController#login(Model)
2021-07-14 08:31:31.329 DEBUG 17152 --- [nio-8080-exec-6] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/webp, application/xml;q=0.9, */*;q=0.8]
2021-07-14 08:31:31.361 DEBUG 17152 --- [nio-8080-exec-6] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2021-07-14 08:31:31.383 DEBUG 17152 --- [nio-8080-exec-8] o.s.security.web.FilterChainProxy        : Securing GET /webjars/bootstrap/4.0.0-2/js/bootstrap.min.js
2021-07-14 08:31:31.384 DEBUG 17152 --- [nio-8080-exec-8] o.s.security.web.FilterChainProxy        : Secured GET /webjars/bootstrap/4.0.0-2/js/bootstrap.min.js
2021-07-14 08:31:31.384 DEBUG 17152 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet        : GET "/JourneyFood/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js", parameters=
2021-07-14 08:31:31.384 DEBUG 17152 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : Securing GET /webjars/bootstrap/4.0.0-2/css/bootstrap.min.css
2021-07-14 08:31:31.384 DEBUG 17152 --- [nio-8080-exec-8] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [Classpath [META-INF/resources/webjars/]]
2021-07-14 08:31:31.385 DEBUG 17152 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : Secured GET /webjars/bootstrap/4.0.0-2/css/bootstrap.min.css
2021-07-14 08:31:31.385 DEBUG 17152 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet        : GET "/JourneyFood/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css", parameters=
2021-07-14 08:31:31.385 DEBUG 17152 --- [nio-8080-exec-7] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [Classpath [META-INF/resources/webjars/]]
2021-07-14 08:31:31.391 DEBUG 17152 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2021-07-14 08:31:31.395 DEBUG 17152 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet        : Completed 200 OK

当我调试通过时,我发现 loadUserByUserName(String username) 中的 username String 是空的("")。请让我知道我在这里做错了什么。请在此处找到相同的源代码。

public class CustomUserDetailsService implements UserDetailsService 
    @Autowired
    private UserRepository userRepo;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException //username is coming null
        // TODO Auto-generated method stub
        UserEntity user = userRepo.findByEmail(username); 
        System.out.println("Email: "+username);
        if(user==null) 
            throw new UsernameNotFoundException(user.getEmail()+" is not registered, please register before logging in.");
        
        return new CustomUserDetails(user);
    


这就是我的 UserDetails 类的样子 - 自定义用户详细信息

公共类 CustomUserDetails 实现 UserDetails

private UserEntity user;

@Override
public Collection<? extends GrantedAuthority> getAuthorities() 
    return null;


    
public CustomUserDetails(UserEntity user) 
    super();
    this.user = user;



@Override
public String getPassword() 
    // TODO Auto-generated method stub
    return user.getPassword();


@Override
public String getUsername() 
    // TODO Auto-generated method stub
    return user.getEmail();


@Override
public boolean isAccountNonExpired() 
    // TODO Auto-generated method stub
    return true;


@Override
public boolean isAccountNonLocked() 
    // TODO Auto-generated method stub
    return true;


@Override
public boolean isCredentialsNonExpired() 
    // TODO Auto-generated method stub
    return true;


@Override
public boolean isEnabled() 
    // TODO Auto-generated method stub
    return user.isEnabled();


public String getNameOfGuide() 
    return user.getNameOfGuide() ;

这是用于数据库连接的主要 UserEntity 类

用户实体

@Entity
@Table(name="users")
public class UserEntity 
    @Id
    @Column(name = "user_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    
    @Column(nullable = false, length = 100)
    private String nameOfCenter;

    @Column(nullable = false, length = 100)
    private String nameOfGuide;
    
    @Column(nullable = false, unique = true, length = 18)
    private String contactNoOfGuide;
    
    @Column(nullable = false, unique = true, length = 70)
    private String email;
    
    @Column(nullable = false, length = 150)
    private String password;
    
    private boolean enabled;
    
    
    public long getId() 
        return id;
    

    public void setId(long id) 
        this.id = id;
    

    public String getNameOfCenter() 
        return nameOfCenter;
    

    public void setNameOfCenter(String nameOfCenter) 
        this.nameOfCenter = nameOfCenter;
    

    public String getNameOfGuide() 
        return nameOfGuide;
    

    public void setNameOfGuide(String nameOfGuide) 
        this.nameOfGuide = nameOfGuide;
    

    public String getContactNoOfGuide() 
        return contactNoOfGuide;
    

    public void setContactNoOfGuide(String contactNoOfGuide) 
        this.contactNoOfGuide = contactNoOfGuide;
    

    public String getEmail() 
        return email;
    

    public void setEmail(String email) 
        this.email = email;
    

    public String getPassword() 
        return password;
    

    public void setPassword(String password) 
        this.password = password;
    

    public boolean isEnabled() 
        return enabled;
    

    public void setEnabled(boolean enabled) 
        this.enabled = enabled;
    

    @Override
    public String toString() 
        return "UserEntity [id=" + id +  ", nameOfCenter=" + nameOfCenter + ", nameOfGuide="
                + nameOfGuide + ", contactNoOfGuide=" + contactNoOfGuide + ", email=" + email + ", password=" + password
                + ", enabled=" + enabled + "]";
    
    
    

在 WebSecurityConfig 中,我创建了登录成功作为成功验证登录页面,否则它应该给出 403 并要求使用无效凭据重新登录:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
    
    @Bean 
    public UserDetailsService userDetailsService() 
        return new CustomUserDetailsService();
    
    
    @Bean
    public BCryptPasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder()  ;
    
    
    @Bean
    public DaoAuthenticationProvider authenticationProvider() 
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService());
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
        auth.authenticationProvider(authenticationProvider());
    
    
    @Override
    protected void configure(HttpSecurity http)throws Exception
        http.authorizeRequests()
        .antMatchers("/users").authenticated()
        .antMatchers("/addJourneyFoodOrder").authenticated()
        .antMatchers("/edit/**").authenticated()
        .antMatchers("/delete/**").authenticated()
        .antMatchers("/h2-console/**","/login","/register").permitAll()
        .and()
        .formLogin()
            .loginPage("/login")
            .defaultSuccessUrl("/login-success")
            .failureUrl("/login?error=true")
        .and()
        .logout().logoutSuccessUrl("/login").permitAll()
        .and()
        .exceptionHandling().accessDeniedPage("/403");
        http.csrf().disable();
        http.headers().frameOptions().disable();        
    
    @Override
    public void configure(WebSecurity web) 
        web.ignoring()
            .antMatchers("/resources/**", "/static/**");
    
       

家庭控制器

@Controller
public class HomeController 

    @Autowired
    private JourneyFoodService journeyFoodServiceImpl;
    
    @Autowired
    private UserService userService;
    
    @GetMapping("/register")
    public String register(final Model model) 
        model.addAttribute("user", new UserSignUpFormData());
        return "register";
    
    
    @PostMapping("/register")//Post operation
    public ModelAndView register(@Valid @ModelAttribute("user")UserSignUpFormData user, BindingResult result,HttpServletRequest request) 
        ModelAndView mav = new ModelAndView("register", "user", user);
        if (result.hasErrors()) 
            return mav;
        
        else 
            try 
                userService.register(user);System.out.println(user);
            catch (UserAlreadyExistException e)
                mav.addObject("message", "An account with this email already exists.");
                return mav;
            
           return new ModelAndView("signup-success", "user", user);
        
    
    
    
   @GetMapping("/login")//to fetch form
    public String login(Model model) 
        model.addAttribute("user", new UserEntity());
        return "login";
    
    

login.html

<html xmlns:th="http://www.thymeleaf.org" xmlns:tiles="http://www.thymeleaf.org">
  <head>
    <title tiles:fragment="title">Messages : Create</title>
    <link th:rel="stylesheet" th:href="@/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css "/>
    <script th:src="@/webjars/bootstrap/js/bootstrap.min.js"></script>
  </head>
  <body>
    <div class="container">
        <form th:action="@/login" th:object="$user" method="post" class="form-signin">               
            <div>
                <div th:if="$param.error" class="alert alert-danger" role="alert" ><h3>Mandatory field validation Errors:</h3>
                    <p class="error"> Invalid credentials</p>
                </div>
            </div>
            <h2 class="mb-5">Login</h2>
               <div class="form-group">
                   <label for="nameOfCenter">Email:</label>
                    <input type="email" th:field="*email" class="form-control" placeholder="Enter email">
               </div>
               <div class="form-group">
                   <label for="password">Password: </label>
                    <input type="password" th:field="*password" class="form-control" placeholder="Enter password">
               </div>
               <button class="btn btn-primary" type="submit">Login</button>
        </form>
    </div>
  </body>
</html>

请帮我解决这个问题,因为我无法弄清楚代码出了什么问题以及需要更改什么。

【问题讨论】:

你能分享你的登录页面吗? 登录界面更新 请在登录时发布完整的调试日志。 在重新加载登录 @Toerktumlare 期间和之后更新了完整日志。源码请找link。 日志中没有登录请求。 【参考方案1】:

电子邮件字段没有与之关联的名称。

默认情况下,“/login”端点需要一个名为“username”的参数。

要将电子邮件作为用户名参数发送,您需要在电子邮件字段中添加名称。

<input name="username" type="email" th:field="*email" class="form-control" placeholder="Enter email">

您可能会在密码字段中遇到同样的问题。

要查看正在发送的参数,您可以在浏览器的“网络”选项卡中查看“/login”请求。

【讨论】:

我尝试了它的电子邮件仍然收到相同的回复。 您是否也添加了密码名称?查看浏览器网络选项卡,看看“/login”的请求是什么样的。 是的,我也添加了密码名称并退休,但它在我的本地没有工作。如果它澄清了什么,请查看我粘贴在上面评论中的 git url。

以上是关于使用 Spring Security 登录失败的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security 多个登录用户失败

Grails Spring Security登录失败未重定向到登录视图

使用 Grails Spring Security Rest 插件时如何获取客户端登录失败的原因?

Spring Security 登录失败后如何停止跳转到登录页面

Spring Security - UserDetailsS​​ervice 实现 - 登录失败

Spring Security:如果身份验证失败,则重定向到登录页面