如何在Spring Security应用程序中添加无状态身份验证?

时间:2020-04-26 08:45:20

标签: spring authentication spring-security session-state stateless

不幸的是,我找不到向Spring Security应用程序添加无状态身份验证的方法。我使用自定义AuthenticationPovider通过覆盖方法doFilter()对AJAX请求和AjaxLoginFilter进行身份验证。在这一步上一切都很好。然后,我添加持久的RememberMe服务。再次,我的应用程序运行良好。现在,我决定通过在configure()中添加.sessionCreationPolicy(SessionCreationPolicy.STATELESS)来进行无状态身份验证。并失败。我的身份验证现在不正确。我的应用程序现在仅需要“本金”即可登录(带有任何“凭据”)。凭据不受检查。我尝试进行无状态身份验证有什么问题?我认为某些authenticate()方法不正确,或者链中的过滤顺序不正确,但是我的经验不足以解决此问题。

我的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);
    }
}

}

我的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<>());
}

我的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 + "\'"));
}

0 个答案:

没有答案
相关问题