具有自定义的用户详细信息服务。如果输入的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);
}