Как добавить аутентификацию без сохранения состояния в моем приложении Spring Security? - PullRequest
0 голосов
/ 26 апреля 2020

К сожалению, я не смог найти способ добавить аутентификацию без сохранения состояния в мое приложение Spring Security. Я использую пользовательский AuthenticationPovider для аутентификации по запросу AJAX и AjaxLoginFilter с методом переопределения doFilter (). И на этом этапе все было хорошо. Затем я добавляю постоянный сервис запомнить меня. И снова мое приложение работает хорошо. Теперь я решил сделать проверку подлинности без сохранения состояния, добавив .sessionCreationPolicy (SessionCreationPolicy.STATELESS) в configure (). И потерпеть неудачу. Моя аутентификация сейчас неверна. Мое приложение требует только "принципала" для входа (с любыми "учетными данными"). Учетные данные стали непроверенными. Что не так с моей попыткой сделать проверку подлинности без сохранения состояния? Я думаю, что какой-то метод authenticate () работает некорректно, или порядок фильтров в цепочке неверен, но мой опыт не настолько высок, чтобы решить этот вопрос.

my AjaxLoginFilter

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    if (httpRequest.getRequestURL().toString().endsWith("/login") &&
            httpRequest.getMethod().matches("POST")) {
        ObjectMapper mapper = new ObjectMapper();
        User user = mapper.readValue(httpRequest.getReader().lines().collect(Collectors.joining()), User.class);
        Authentication auth = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        SecurityContextHolder.getContext().setAuthentication(auth);
        chain.doFilter(request, response);
    } else {
        chain.doFilter(request, response);
    }
}

}

my WebSecurityConfig

public static final String KEY = "posc";

@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
    return new BCryptPasswordEncoder();
}

@Autowired
UserService userService;

@Autowired
private AjaxAuthenticationProvider ajaxProvider;

@Autowired
DataSource dataSource;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    auth
            .userDetailsService(userService);
    auth
            .authenticationProvider(this.ajaxProvider)
            .authenticationProvider(new RememberMeAuthenticationProvider(KEY));
}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
            .antMatchers("/**/*.css")
            .antMatchers("/**/*.js")
            .antMatchers("/**/*.png")
            .antMatchers("/**/*.ico")

    ;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers("/login")
            .permitAll()
            .antMatchers("/editor.html")
            .hasRole("ADMIN")
            .and()
            .authorizeRequests()
            .antMatchers("/resources/**")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .loginPage("/login.html")
            .permitAll()
            .defaultSuccessUrl("/index.html")
            .and()
            .exceptionHandling().accessDeniedPage("/error.html")
            .and()
            .logout()
            .logoutUrl("/customlogout.html")
            .logoutSuccessUrl("/login.html")
            .permitAll()
            .and()
            .rememberMe()
            .rememberMeServices(rememberMeServices());
}

@Bean
public PersistentTokenRepository persistentTokenRepository() {
    JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
    db.setDataSource(dataSource);
    return db;
}

@Bean
public AbstractRememberMeServices rememberMeServices() {
    PersistentTokenBasedRememberMeServices rememberMeServices =
            new PersistentTokenBasedRememberMeServices(KEY, userService, persistentTokenRepository());
    rememberMeServices.setAlwaysRemember(true);
    rememberMeServices.setCookieName("remember-me-posc");
    rememberMeServices.setTokenValiditySeconds(1209600);
    return rememberMeServices;
}

}

и мой LoginController

    private AuthenticationManager authenticationManager;

@Autowired
private RememberMeServices rememberMeServices;

@PostMapping("/login")
public ResponseEntity login(final HttpServletRequest request, final HttpServletResponse response) {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Type", "application/json");
    Authentication authenticationFromContext =
            SecurityContextHolder.getContext().getAuthentication();
    rememberMeServices.loginSuccess(request, response, authenticationFromContext);
    System.out.println("My login controller");
    return ResponseEntity.ok(new HashMap<>());
}

my UserService

    private final UserRepository userRepository;
private static List<User> users = new ArrayList();

public UserService(UserRepository userRepository) {
    this.userRepository = userRepository;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    return userRepository.findByUsername(username)
            .map(UserDetailsAdapter::new)
            .orElseThrow(() -> new UsernameNotFoundException("Can't found username \'" + username + "\'"));
}
...