无法使用 Spring 安全登录 - 使用外部数据库的基于注释的配置

Posted

技术标签:

【中文标题】无法使用 Spring 安全登录 - 使用外部数据库的基于注释的配置【英文标题】:Unable to login with Spring security -Annotation based configuration with external database 【发布时间】:2016-08-01 04:57:15 【问题描述】:

我正在按照这些 1 2 链接配置 Spring Security。我的问题是 Spring Security 的默认登录页面没有在我的应用程序中呈现,即我能够点击所有 url。我错过了什么下面是我的配置。

WebSecurityConfigurerAdapterImplementaion-

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 
    @Autowired
    private DataSource dataSource;

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder registry) throws Exception 
        registry.userDetailsService(customUserDetailsService);
    

      @Override
      public void configure(WebSecurity web) throws Exception 
        web.ignoring().antMatchers("/resources/**");
      

      @Override
      protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable()
        .authorizeRequests()
            .antMatchers("/login","/login/form**","/register","/logout").permitAll()
            .antMatchers("/admin","/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login/form")
            .loginProcessingUrl("/login")
            .failureUrl("/login/form?error")
            .permitAll();
      

UserDetailsService 实现

@Component
public class CustomUserDetailsService implements UserDetailsService

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException 
        User user = userService.findUserByEmail(userName);
        if(user == null)
            throw new UsernameNotFoundException("UserName "+userName+" not found");
        
        return new SecurityUser(user);
    

User 实现-

public class SecurityUser extends User implements UserDetails


    private static final long serialVersionUID = 1L;
    public SecurityUser(User user) 
        if(user != null)
        
            this.setId(user.getId());
            this.setName(user.getName());
            this.setEmail(user.getEmail());
            this.setPassword(user.getPassword());
            this.setDob(user.getDob());
            this.setRoles(user.getRoles());
               
    

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

        Collection<GrantedAuthority> authorities = new ArrayList<>();
        List<Role> userRoles = this.getRoles();

        if(userRoles != null)
        
            for (Role role : userRoles) 
                SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getRoleName());
                authorities.add(authority);
            
        
        return authorities;
    

    @Override
    public String getPassword() 
        return super.getPassword();
    

    @Override
    public String getUsername() 
        return super.getEmail();
    

    @Override
    public boolean isAccountNonExpired() 
        return true;
    

    @Override
    public boolean isAccountNonLocked() 
        return true;
    

    @Override
    public boolean isCredentialsNonExpired() 
        return true;
    

    @Override
    public boolean isEnabled() 
        return true;
       

我的SpringWebAppInitializer 班级是-

public class SpringWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer

    @Override
    protected Class<?>[] getServletConfigClasses()
    
        return new Class<?>[]   AppConfig.class ;
    

    @Override
    protected String[] getServletMappings()
    
        return new String[]  "/" ;
    

    @Override
    protected Class<?>[] getRootConfigClasses()
    
        return new Class<?>[]  AppConfig.class;
    



    @Override
    protected Filter[] getServletFilters() 
       return new Filter[] 
               new DelegatingFilterProxy("springSecurityFilterChain"),
               new OpenEntityManagerInViewFilter();
     


此外,我尝试使用我的自定义登录页面,即使这也没有渲染-

<form:form id="loginForm" method="post" action="$appUrl/controller/login"
                    modelAttribute="user" class="register" role="form">
                    <div class="form-group">
                        <div class="">
                            <input type="text" id="username" name="username"
                                class="form-control register-input" placeholder="UserName" />
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="">
                            <input type="password" id="password" name="password"
                                class="form-control register-input" placeholder="Password" />
                        </div>
                    </div>
                    <input type="hidden" name="$_csrf.parameterName"  value="$_csrf.token" />
                    <div class="form-group">
                        <div class="col-sm-offset-3">
                            <input type="submit" class="btn btn-primary" value="Login">
                        </div>
                    </div>
                </form:form>

【问题讨论】:

【参考方案1】:

如果你想使用默认的spring登录页面,你不要放:

.formLogin()
        .loginPage("/login/form")  <--- this line is not needed for default spring login
        .loginProcessingUrl("/login")
        .failureUrl("/login/form?error")
        .permitAll(); <--- and this no need too

根据您上面的配置,您正在使用自己的登录页面。 另一件事是您的表单登录。

请注意如果您使用标签form,您也需要在输入时使用它。

例子:

<form:form modelAttribute="foo" method="post" ...
<form:input type="text" id="username" path="username" ....

通过使用标签form,您需要包含modelAttribute=""并在控制器中将其调用为@ModelAttribute("foo") Users users,您应该注意到标签form&lt;input&gt;中没有使用name,而是它们是使用path

但是,您也可以使用不带标签form 的普通形式,如果您使用它,则无需包含modelAttribute="" 并将其用作普通形式。

如果你的 spring security 没有触发或者你仍然可以点击任何地方,那是因为SpringWebAppInitializer 没有加载你的安全配置并且它不知道配置是否存在。我建议你查找WebApplicationInitializer

【讨论】:

以上是关于无法使用 Spring 安全登录 - 使用外部数据库的基于注释的配置的主要内容,如果未能解决你的问题,请参考以下文章

Keycloak - spring boot - 外部登录网页

无法使用 Angular 2 作为前端并使用基本 Http 身份验证获取有关 Spring 安全性的登录详细信息

如何解决在使用 Spring Boot 和 Spring Security 启用 CSRF 后无法正常工作的登录问题?

使用注释的Spring安全登录数据库:NoSuchBeanDefinitionException

将cookie设置为安全时Spring Boot无法登录

具有多个提供程序的 Spring 安全性