java - 登录时访问被拒绝页面

标签 java spring spring-boot spring-security

我能够在我的 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/

相关文章:

java - Jgit中 'pull'命令的使用

java - 使用java代码更改ubuntu系统时间

java - 在 tomcat 中部署 Spring Boot war 时,application.yml 文件应该放在哪里?

java - Spring Redis Hash 操作 SCAN

java - 为网站添加额外的安全性

java - 将 JVM 参数添加到 Spring Boot 应用程序

java - JRebel 曾经在生产环境中使用过吗?它可以在 JVM 上重新加载什么?

java - 如何在@InitBinder 验证之前执行代码

java - 无法从字符串中反序列化类型为 `java.util.Date` 的值

java - Spring Boot jdbc 数据源自动配置在独立 tomcat 上失败