具有自定义的用户详细信息服务。如果输入的URL未在安全配置的“允许所有列表”中列出。它将被重定向到登录名并作为错误登录名处理。然后,如果我使用正确的用户名和密码直接登录,它将不会被重定向到默认的成功URL,它将转到我之前输入的先前错误的URL。这是什么意思?我的代码有什么问题。请帮我!

这是我的用户详细信息服务的实现

   @Service
   public class UserDetailsServiceImpl implements UserDetailsService{
   @Autowired
   private UserRepository userRepository;

  @Override
  @Transactional(readOnly = true)
  public UserDetails loadUserByUsername(String email) throws
  UsernameNotFoundException {

   User user = userRepository.findByEmail(email);
           Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
          for (Role role : user.getRoles()){
          grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
    }
    return new org.springframework.security.core.userdetails.User(user.getEmail(),
 user.getPassword(), grantedAuthorities);


}

这是我的安全配置类

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;

 @Autowired
 private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth
            .userDetailsService(userDetailsService)
            .passwordEncoder(bCryptPasswordEncoder);
    }

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


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

    http.
        authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/signin").permitAll()

            .antMatchers("/confirm").permitAll()
            .antMatchers("/index").permitAll()
            .antMatchers("/adminpage").permitAll()
            .antMatchers("/register").permitAll()
            .antMatchers("/login").permitAll()

   .antMatchers("/library/**","/admin").hasAuthority("ADMIN").anyRequest()
            .authenticated().and().csrf().disable().formLogin()
            .loginPage("/login").failureUrl("/login?error=true")
            .defaultSuccessUrl("/index")
            .usernameParameter("email")
            .passwordParameter("password")
            .and().logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/").and().exceptionHandling()
            .accessDeniedPage("/access-denied");

}

@Override
public void configure(WebSecurity web) throws Exception {
    web
       .ignoring()
       .antMatchers("/resources/**", "/static/**", "/css/**", "/js/**",
"/img/**","/fonts/**")
 ;  }

最佳答案

此行为是由于SavedRequestAwareAuthenticationSuccessHandler。如类SavedRequestAwareAuthenticationSuccessHandler的javadoc api中所述:


  可以使用ExceptionTranslationFilter可能已存储在会话中的DefaultSavedRequest的身份验证成功策略。当此类请求被拦截并需要进行身份验证时,将存储请求数据以记录身份验证过程开始之前的原始目的地,并允许在重定向到相同URL时重构请求。如果合适,此类负责执行重定向到原始URL的操作。
  
  成功进行身份验证后,它将根据以下情况决定重定向目标:
  
  
  如果alwaysUseDefaultTargetUrl属性设置为true,则将defaultTargetUrl用于目标。会话中存储的所有DefaultSavedRequest将被删除。
  如果已在请求上设置了targetUrlParameter,则该值将用作目标。任何DefaultSavedRequest将再次被删除。
  如果在RequestCache中找到SavedRequest(由ExceptionTranslationFilter设置为在身份验证过程开始之前记录原始目的地),则将执行重定向到该原始目的地的Url。当收到重定向的请求时,SavedRequest对象将保持高速缓存并被拾取(请参阅SavedRequestAwareWrapper)。
  如果未找到SavedRequest,它将委派给基类。
  


如果要跳过此行为并始终重定向到默认成功URL,则可以仅使用方法defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse)而不是仅使用defaultSuccessUrl(String defaultSuccessUrl)来实现,当然,将第二个参数设置为布尔值也可以这样:

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

    http.
        authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/signin").permitAll()

            .antMatchers("/confirm").permitAll()
            .antMatchers("/index").permitAll()
            .antMatchers("/adminpage").permitAll()
            .antMatchers("/register").permitAll()
            .antMatchers("/login").permitAll()

   .antMatchers("/library/**","/admin").hasAuthority("ADMIN").anyRequest()
            .authenticated().and().csrf().disable().formLogin()
            .loginPage("/login").failureUrl("/login?error=true")
            .defaultSuccessUrl("/index", true)
            .usernameParameter("email")
            .passwordParameter("password")
            .and().logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/").and().exceptionHandling()
            .accessDeniedPage("/access-denied");

}


这是github repo中Spring security的AbstractAuthenticationFilterConfigurer类的方法defaultSuccessUrl(String defaultSuccessUrl)defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse)的源代码:

/**
     * Specifies where users will go after authenticating successfully if they have not
     * visited a secured page prior to authenticating. This is a shortcut for calling
     * {@link #defaultSuccessUrl(String)}.
     *
     * @param defaultSuccessUrl the default success url
     * @return the {@link FormLoginConfigurer} for additional customization
     */
    public final T defaultSuccessUrl(String defaultSuccessUrl) {
        return defaultSuccessUrl(defaultSuccessUrl, false);
    }

    /**
     * Specifies where users will go after authenticating successfully if they have not
     * visited a secured page prior to authenticating or {@code alwaysUse} is true. This
     * is a shortcut for calling {@link #successHandler(AuthenticationSuccessHandler)}.
     *
     * @param defaultSuccessUrl the default success url
     * @param alwaysUse true if the {@code defaultSuccesUrl} should be used after
     * authentication despite if a protected page had been previously visited
     * @return the {@link FormLoginConfigurer} for additional customization
     */
    public final T defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse) {
        SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler();
        handler.setDefaultTargetUrl(defaultSuccessUrl);
        handler.setAlwaysUseDefaultTargetUrl(alwaysUse);
        return successHandler(handler);
}

10-04 12:41