Доступ запрещен на странице при входе - PullRequest
0 голосов
/ 02 апреля 2020

Мне удалось войти в систему с помощью Spring Security в моем приложении Spring. Затем я ввел неправильные учетные данные, и страница с отказом в доступе работала, как и ожидалось. После этого я попытался войти с правильными учетными данными, но страница с отказом в доступе загружается всегда. Может кто-то объяснить решение?

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;
    }
}

1 Ответ

1 голос
/ 03 апреля 2020

Прежде чем пытаться выяснить, почему доступ запрещен на странице, UsernamePasswordAuthenticationToken с конструктором из 3 аргументов всегда устанавливает флаг аутентификации в значение true.

UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(
            userDetails,password,userDetails.getAuthorities());

, поэтому проверяется, будет ли аутентифицированный результат истинным, а не реальным статусом на основе аутентификации, так как вы полагаетесь на if(result){...}:

boolean result = token.isAuthenticated();<- always true

, так как при попытке аутентификации токен authenticationManager.authenticate(token); здесь должен представлять объект аутентификации, построенный из учетных данных пользователя, например:

UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(enteredUserName,enteredPassword);

, который передается диспетчеру аутентификации, который, в свою очередь, делегирует зарегистрированным провайдерам аутентификации для аутентификации. Я думаю, что ваш SecurityServiceImpl имитирует логин провайдера аутентификации c. Я бы предложил перенести этот лог c в реализацию AuthenticationProvider и зарегистрировать его в AuthenticationManagerBuilder. Basi c пример:

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

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...