AngularJS:POST请求返回后发送的GET请求,302用于登录

时间:2016-05-02 18:48:42

标签: angularjs login spring-security httprequest http-redirect

我正在实施一个用于身份验证的登录页面。 AngularJS使用用户凭据向服务器发送发布请求。

//service.js
authApp.factory("loginFactory", function ($http) {
    return{
        login: function(username, password) {
            var data = {username: username, password: password};
            serialize = function(obj) {
              var str = [];
              for(var p in obj)
                if (obj.hasOwnProperty(p)) {
                  str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                }
              return str.join("&");
            }

            return $http({
                method: 'POST',
                url: 'http://localhost:8080/login',
                data: serialize(data),
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                }
            });  
        }
    }   
});

我的控制器处理成功和失败。出于调试目的,我只打印出响应而不是重定向。

authApp.controller('LoginCtrl', ['$scope', '$location', 'loginFactory', function($scope, $location, loginFactory){
    $scope.authenticate = function() {
        loginFactory.login($scope.username, $scope.password)
        .then(function(response) {
            console.log(response);
        }, function errorCallBack(response) {
            console.log(response);
        });
    }
}]);

当我运行它时,POST请求将返回302而没有响应。并且GET请求将立即开始。如果密码正确,则会将其重定向到" http://localhost:8080/"。如果密码错误,它将被重定向到" http://localhost:8080/login?error。由于我没有任何一个路径的处理程序,它将返回401错误。 Angular控制器将捕获来自GET请求的响应,就好像它是来自Post请求的响应一样。

在后端,由Spring Security完成身份验证。这是安全配置:

protected void configure(HttpSecurity http) throws Exception {
        http
            .httpBasic().and()
            .addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class)
            .csrf().disable()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
            .formLogin();
                //.loginPage("/login");
    }

GET请求来自哪里?为什么原始帖子请求会触发重定向?

1 个答案:

答案 0 :(得分:1)

GET请求是由于服务器返回302。在传统的登录形式中,spring将:

  1. 处理POST登录请求
  2. 在成功和错误的情况下重定向到成功页面(/)('/ login?error`)
  3. 浏览器透明地处理重定向。

    如果您想更改spring的默认行为,我建议您参考tutorial。本教程使用基本身份验证而不是表单登录。但是,如果您需要表单登录,则必须实现自定义身份验证成功和失败处理程序。如下所示:

    安全配置

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/login","/error").permitAll()
                .anyRequest()
                .fullyAuthenticated().and().formLogin()
                .failureHandler(customAuthenticationFailureHandler).and()
                .logout().logoutSuccessHandler(ajaxLogoutSuccessHandler);
        http.exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(customAccessDeniedHandler);
    
    }
    

    CustomAuthenticationFailureHandler返回状态代码401,而不是重定向到失败处理程序URL。

    @Component
    public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
    
        @Override
        public void onAuthenticationFailure(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException exception)
        throws IOException, ServletException {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    
        }
    
    }
    

    AjaxLogoutSuccessHandler返回状态200而不是重定向到注销成功网址

    @Component
    public class AjaxLogoutSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler
            implements LogoutSuccessHandler {
    
        @Override
        public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
                                    Authentication authentication)
                throws IOException, ServletException {
            response.setStatus(HttpServletResponse.SC_OK);
        }
    }
    

    CustomAuthenticationEntryPoint返回401而不是重定向到登录页面

    @Component
    public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    
        @Override
        public void commence(HttpServletRequest request,
                HttpServletResponse response, AuthenticationException authException)
                throws IOException, ServletException {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    
        }
    
    }
    

    CustomAccessDeniedHandler返回401而不是重定向到访问被拒绝的页面。

    @Component
    public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    
        @Override
        public void handle(HttpServletRequest request,
                HttpServletResponse response,
                AccessDeniedException accessDeniedException) throws IOException,
                ServletException {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    
        }
    
    }
    

    我希望这会有所帮助。