我能够在我的 Spring Boot 应用程序中使用 Spring Security 登录。然后我输入了错误的凭据,访问拒绝页面按预期工作。之后我尝试使用正确的凭据登录,但访问拒绝页面始终加载。有人可以吗解释一下解决方案?
WebSecurityConfig.java
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/showReg", "/", "/index.html", "/registerUser", "/login", "/showLogin", "/login/*")
.permitAll()
.anyRequest()
.authenticated();
http
.csrf().disable()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/showLogin")
.deleteCookies("remember-me").permitAll()
.and()
.rememberMe();
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
SecutityServiceImpl.java
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
@Service
public class SecurityServiceImpl implements SecurityService {
@Autowired
UserDetailsService userDetailsService;
@Autowired
AuthenticationManager authenticationManager;
@Override
public boolean login(String userName, String password) {
UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(
userDetails,password,userDetails.getAuthorities());
authenticationManager.authenticate(token);
boolean result = token.isAuthenticated();
if (result){
SecurityContextHolder.getContext().setAuthentication(token);
}
return result;
}
}
最佳答案
在尝试找出访问被拒绝页面的原因之前, 具有 3 个参数构造函数的 UsernamePasswordAuthenticationToken 始终将身份验证标志设置为 true。
UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(
userDetails,password,userDetails.getAuthorities());
因此检查身份验证结果是否为真,这不是您在 if(result){...}
中所依赖的真正基于身份验证的状态:
boolean result = token.isAuthenticated();<- always true
对于尝试进行身份验证 authenticationManager.authenticate(token);
此处的 token 应表示由用户凭据构造的身份验证对象,如下所示:
UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(enteredUserName,enteredPassword);
它被传递给身份验证管理器,身份验证管理器又委托(delegate)注册的身份验证提供者进行身份验证。 我认为您的 SecurityServiceImpl 模仿身份验证提供程序逻辑。我建议将该逻辑引入 AuthenticationProvider 实现并将其注册到 AuthenticationManagerBuilder。 基本示例:
@Component
public class AuthProvider implements AuthenticationProvider {
@Autowired
UserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String enteredUserName = authentication.getName();
String enteredPassword = authentication.getCredentials().toString();
UserDetails ud = userDetailsService.loadUserByUsername(userName);
// compare/check password
// if password valid
return new UsernamePasswordAuthenticationToken(ud,null,authorities);
}
@Override
public boolean supports(Class<?> aClass) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
}
}
关于java - 登录时访问被拒绝页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60989440/