在我的(java spring mvc + mysql 应用程序,thymeleaf)中实现 spring 安全性后,身



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

一种身份验证成功策略,可以利用 DefaultSavedRequest,该请求可能已由 ExceptionTranslationFilter 存储在会话中。当此类请求被截获并需要身份验证时,将存储请求数据以在身份验证过程开始之前记录原始目标,并允许在重定向到同一 URL 时重建请求。此类负责执行到原始 URL 的重定向(如果适用)。

身份验证成功后,它会根据以下方案确定重定向目标:

  • 如果 alwaysUseDefaultTargetUrl 属性设置为 true,则将 defaultTargetUrl 用于目标。存储在会话中的任何 DefaultSavedRequest 都将被删除。
  • 如果在请求上设置了 targetUrlParameter,则该值将用作目标。任何 DefaultSavedRequest 都将再次被删除。
  • 如果在 RequestCache 中找到 SavedRequest(由 ExceptionTranslationFilter 设置,用于在身份验证过程开始之前记录原始目标),则将执行重定向到该原始目标的 URL。SavedRequest 对象将保持缓存状态,并在收到重定向请求时拾取(请参阅 SavedRequestAwareWrapper)。 如果未找到 SavedRequest,它将委托给基类。

如果你想跳过这种行为并全部重定向到默认的成功网址,你可以只使用方法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");
}

这是从 Spring security 的 AbstractAuthenticationFilterConfigurer 类在 github 存储库中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);
}

最新更新