java - 在我的(java spring mvc + mysql应用程序,thymeleaf)中实现spring security后,身份验证发生了一些奇怪的事情

标签 java spring-mvc spring-boot spring-security thymeleaf

拥有自定义用户详细信息服务。如果我输入的 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 中所述:

An authentication success strategy which can make use of the DefaultSavedRequest which may have been stored in the session by the ExceptionTranslationFilter. When such a request is intercepted and requires authentication, the request data is stored to record the original destination before the authentication process commenced, and to allow the request to be reconstructed when a redirect to the same URL occurs. This class is responsible for performing the redirect to the original URL if appropriate.

Following a successful authentication, it decides on the redirect destination, based on the following scenarios:

  • If the alwaysUseDefaultTargetUrl property is set to true, the defaultTargetUrl will be used for the destination. Any DefaultSavedRequest stored in the session will be removed.
  • If the targetUrlParameter has been set on the request, the value will be used as the destination. Any DefaultSavedRequest will again be removed.
  • If a SavedRequest is found in the RequestCache (as set by the ExceptionTranslationFilter to record the original destination before the authentication process commenced), a redirect will be performed to the Url of that original destination. The SavedRequest object will remain cached and be picked up when the redirected request is received (See SavedRequestAwareWrapper). If no SavedRequest is found, it will delegate to the base class.

如果您想跳过此行为并始终重定向到默认成功网址,则只需使用方法 defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse) 而不是仅使用 defaultSuccessUrl(String defaultSuccessUrl ),当然,将第二个参数设置为 boolean 值,就像这样:

@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");

}

这是来自 Spring security 的 AbstractAuthenticationFilterConfigurer 的方法 defaultSuccessUrl(String defaultSuccessUrl)defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse) 的源代码github 存储库中的类:

/**
     * 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);
}

关于java - 在我的(java spring mvc + mysql应用程序,thymeleaf)中实现spring security后,身份验证发生了一些奇怪的事情,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48417066/

相关文章:

java - RequestMappingHandlerMapping 是 RestController 的截断路径

java - Springfox Swagger : Could not resolve pointer:/definitions/Instant

java - spring-boot 更新到 1.3.1 后 webapp 无法启动

java - 为 JAX-WS 客户端设置 SSL

java - Android 初学者 - 在不同 Activity 中使用变量或文件的方法?

multithreading - Spring @Controller 生命周期

java - 学习spring时出错

java - SpringBoot/RabbitMq 集成测试在不同环境下不再工作

java - 如何在任何地方访问 LibGDX 的 ApplicationAdapter 实例

java - 调用 onResponse 时应用程序崩溃