Spring Boot + Security + jQuery AJAX

spring boot + security + jquery ajax

提问人:Tony 提问时间:2/14/2017 更新时间:11/17/2023 访问量:8050

问:

嗨,我用spring boot和spring安全性构建了一个项目。现在,我想为 Jquery.ajax({...}) 提供登录 restfull 服务;我想:

  1. 处理来自 HTML 页面的登录请求(如提交)。<form>
  2. 自动检查 HTML 页面请求时会话超时,将超时重定向到登录页面。
  3. 处理来自 Ajax 的登录请求。
  4. 自动检查 Ajax 请求时的登录状态。

我是这样编码的

SecurityConfig 安全配置

从 WebSecurityConfigurerAdapter 扩展

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();

    http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
        String requestType = request.getHeader("x-requested-with");
        if (!StringUtils.isEmpty(requestType)) {
            response.setStatus(HttpServletResponse.SC_OK);
            response.getWriter().print("{\"invalid_session\": true}");
            response.getWriter().flush();
        } else {
            response.sendRedirect("/security/login");
        }
    });

    http.authorizeRequests()
            .antMatchers("/security/**").permitAll()
            .antMatchers("/reader/**").hasRole("READER")
            .anyRequest().authenticated()

            // session time out
            .and().sessionManagement().invalidSessionUrl("/security/session_timeout")

            .and().cors()

            // login
            .and()
            .formLogin()
            .successHandler(successHandler)
            .failureHandler(faildHandler)
            .loginPage("/security/login")
            .permitAll()

            // logout
            .and()
            .logout().permitAll();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(readerRepository::findOne);
}

我有两个处理程序来处理 AuthenticationSuccess 和 AuthenticationFailure

FailureHandler (失败处理程序)

从 SimpleUrlAuthenticationFailureHandler 扩展

@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
    System.out.println("Failed to auth.");
    String requestType = request.getHeader("x-requested-with");
    if (!StringUtils.isEmpty(requestType)) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().print("{\"success\": false}");
    } else {
        setDefaultFailureUrl("/security/login?error=true");
        super.onAuthenticationFailure(request, response, exception);
    }
}

成功处理程序

从 SavedRequestAwareAuthenticationSuccessHandler 扩展

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    System.out.println("Success to auth.");
    String requestType = request.getHeader("x-requested-with");
    if (!StringUtils.isEmpty(requestType)) {
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().print("{\"success\": true}");
    } else {
        setDefaultTargetUrl("/index/index");
        setAlwaysUseDefaultTargetUrl(true);
        super.onAuthenticationSuccess(request, response, authentication);
    }
}

控制器

base RequestMapping 为 '/security'

@RequestMapping(value = "/login")
public String login(@RequestParam(value = "error", defaultValue = "false") boolean error, Model model) {
    model.addAttribute("error", error);
    return "login";
}

@RequestMapping("/session_timeout")
public void sessionTimeout(HttpServletRequest request, HttpServletResponse response) throws IOException {
    System.out.println("session was timeout.");
    if (request.getHeader("x-requested-with") != null) {
        // handler for ajax
        response.getWriter().print("{\"sessionTimeout\": true}");
        response.getWriter().close();
    } else {
        response.sendRedirect("login");
    }
}

当我在页面(thymeleaf)中测试时,所有工作都有效。 但是..当我使用Jquery Ajax时。 保证:

当我使用 Jquery.ajax({}) API 发送请求时,请求无法到达服务器。如何使用jquery编写ajax请求,我尝试了很多Jquery方法,页面在控制台中没有响应代码。Spring Security 不支持 ajax 吗?

Ajax Spring spring-boot spring-security

评论

0赞 Fan Jin 4/4/2017
你能提供你的ajax javascript代码以及服务器响应状态代码吗?

答:

0赞 Tony 4/5/2017 #1

谢谢范,我修好了。我重写了登录身份验证:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails, userReq.getPassword(), userDetails.getAuthorities());
authenticationManager.authenticate(token);
if (token.isAuthenticated()) {
    SecurityContextHolder.getContext().setAuthentication(token);
    return true;
}

使用 AuthenticationManager 进行身份验证,它从 spring 注入。

如果身份验证成功,我会将 sessionid 返回给客户端并保存在 cookie 中的客户端,当客户端请求时,客户端始终在 ajax 请求的 url 末尾统计 sessionid。 如果身份验证失败,我将返回商定的错误代码。

例如:

$.ajax({
   url: 'http://test:port/project/list;jsessionid=' + jessionid,
   ...
})

但我不认为这样的工作是好的。这很麻烦,在客户端中,我需要检查每个请求的每个响应代码是否正确。有没有更好的方法来解决这个问题??

顺便说一句,客户端(浏览器 + Ajax)和服务器(Spring mvc)是分开的。

评论

0赞 Fan Jin 4/5/2017
嘿托尼,我认为你不需要把 作为 ajax 请求的一部分。Cookie 将作为请求标头的一部分自动发送到服务器。我有一个关于 Spring Boot 和 JWT 身份验证的 github 存储库。其中的代码可能对您有所帮助。这是存储库的 URL:github.com/bfwg/springboot-jwt-starterjsessionidjsessionid