【问题标题】:Spring Security: redirect to single page app in case of 401Spring Security:在 401 的情况下重定向到单页应用程序
【发布时间】:2021-03-01 04:39:29
【问题描述】:

当我在浏览器中输入我的 React 应用程序的任何路由时,例如:http://localhost/login,请求到达我的服务器,我的服务器以 401 Unauthorized 响应。

当请求不是授权的后端 api 时,我想在我的反应路由中处理请求。

WebSecurityConfig.java:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            ...
            .formLogin()
                .disable()
            .authorizeRequests()
                .antMatchers(
                    "/error",
                    "/",
                    "/favicon.ico",
                    "/static/**",
                    "/api/auth/**",
                    "/api/oauth2/**",
                    "/api/courses/**",
                    "/api/stripe/**",
                    "/api/lesson/content")
                    .permitAll()
                .anyRequest()
                    .authenticated()
                .and()
            ...
            .exceptionHandling()
                .authenticationEntryPoint(new RestAuthenticationEntryPoint())
                .and();

    http.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}

RestAuthenticationEntryPoint.java:

public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest httpServletRequest,
                         HttpServletResponse httpServletResponse,
                         AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,
                e.getLocalizedMessage());
    }
}

有没有办法将请求转发到 RestAuthenticationEntryPoint 中的 index.html?

【问题讨论】:

  • When request is not an authorized backend api 什么意思?
  • 当它不匹配任何 antMatchers 并转到 RestAuthenticationEntryPoint.java。
  • 为什么你不只是在/** 上提供你的 react 应用程序,然后在路由器中通过向 /user 发出请求或其他什么来检查他们是否已登录,如果他们没有登录,你会重定向他们登录。到达/api 的每个请求都会返回 401

标签: java spring spring-boot spring-security single-page-application


【解决方案1】:

您可以在 react 中处理 401

axios.post('http://localhost:8080/login', data)
    .then(resp => ...)
    .catch(e => {
        if (e.response && e.response.status===401) 
            history.push('/error');
    });

或者你可以修改你的AuthenticationHandler:

    @Override
    public void commence(HttpServletRequest httpServletRequest,
                         HttpServletResponse httpServletResponse,
                         AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.sendRedirect("http://localhost:3000/error");
    }

【讨论】:

    【解决方案2】:

    我决定从 RestAuthenticationEntryPoint 抛出 404 Not Found 异常,因为我认为它比 401 Unathorized 更符合这个用例:

        @Override
        public void commence(HttpServletRequest httpServletRequest,
                             HttpServletResponse httpServletResponse,
                             AuthenticationException e) throws IOException, ServletException {
            httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND,
                    e.getLocalizedMessage());
        }
    

    并将未发现异常重定向到前端:

        @Bean
        public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer() {
            return container -> {
                container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
                        "/notFound"));
            };
        }
    
    @Controller
    public class CustomErrorController {
    
        @ResponseStatus(HttpStatus.OK)
        @RequestMapping(value = "/notFound")
        public String error() {
            return "forward:/index.html";
        }
    
    }
    

    这种方法的缺点是我不能从任何控制器抛出 404,因为它不会返回到前端,但我可以忍受它。

    【讨论】:

      猜你喜欢
      • 2015-11-30
      • 2015-12-13
      • 2016-09-27
      • 1970-01-01
      • 2013-10-05
      • 2015-08-17
      • 2014-01-11
      • 2012-07-12
      • 2013-03-07
      相关资源
      最近更新 更多