Spring Boot安全性MVC + AngularJS注销无效

时间:2016-03-29 21:16:44

标签: angularjs rest spring-mvc spring-security spring-boot

我在使用AngularJS从Spring Boot https注销时遇到问题。在我刷新页面成功注销后(使用F5),我仍然在此窗口会话中获得第一个登录用户。

我正在使用基本认证,我的tomcat有两个端口:
8090 - http
8443 - https

8090用于重定向安全会话。

我尝试了很多解决方案,但迄今为止都没有。

这是我的配置:
application.properties

server.port=8443
server.ssl.key-store=****.p12
server.ssl.key-storepassword=*****
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=*****

SpringBoot主类

@SpringBootApplication
@EnableJpaRepositories
public class DanceSchoolManagementApplication {

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint securityConstraint = new SecurityConstraint();
                securityConstraint.setUserConstraint("CONFIDENTIAL");
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                securityConstraint.addCollection(collection);
                context.addConstraint(securityConstraint);
            }
        };

        tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
        return tomcat;
    }

    private Connector initiateHttpConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        connector.setPort(8090);
        connector.setSecure(false);
        connector.setRedirectPort(8443);

        return connector;
    }

    public static void main(String[] args) {
        SpringApplication.run(DanceSchoolManagementApplication.class, args);
    }
}

SecurityConfiguration

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private ManagementSecurityProperties managementSecurityProperties;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private LogoutSuccess logoutSuccess;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .httpBasic()
            .and()
            .authorizeRequests()
            .antMatchers("/index.html", "/")
            .permitAll()
            .anyRequest()
//                .authenticated()
            .fullyAuthenticated()

//                .and()
//                .logout()
//                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
//                .logoutSuccessUrl("/")
//                .logoutSuccessHandler(logoutSuccess)
//                .deleteCookies("JSESSIONID")
//                .invalidateHttpSession(true)
//                .permitAll()

            .and()
            .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
            .csrf().csrfTokenRepository(csrfTokenRepository())

            .and()
            .sessionManagement()
            .maximumSessions(1)
            .maxSessionsPreventsLogin(true);
    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        return repository;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(createDaoAuthenticationProvider());
    }

    private DaoAuthenticationProvider createDaoAuthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
        daoAuthenticationProvider.setPasswordEncoder(createBCryptPasswordEncoder());
        return daoAuthenticationProvider;
    }

    @Bean
    public PasswordEncoder createBCryptPasswordEncoder() {
        return new BCryptPasswordEncoder(managementSecurityProperties.getBcryptStrength());
    }


}

如您所见,我尝试了许多不同的配置选项,包括创建自己的LogoutSuccessHandlers,尝试删除cookie并使会话无效,但其中任何一个都适用于我。

以下是自定义注销休息方法:

@RequestMapping(method = RequestMethod.POST, value = "/auth/logout")
public boolean logout(HttpServletRequest request, HttpServletResponse response) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if(auth != null) {
            new SecurityContextLogoutHandler().logout(request,response,auth);
            auth = null;
            SecurityContextHolder.getContext().setAuthentication(auth);
            SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
        }

        return true;
}

但是在刷新页面后我仍然能够获得经过身份验证的用户数据:

这是角度登录和注销:

验证服务

angular.module("danceSchoolManagement.authService",[])
.factory("authService", function ($http) {
    var service = {};

    service.authenticate = function(credentials, successFunction, failureFunction) {
        var headers = credentials ? {
            authorization: "Basic "
            + btoa(credentials.username + ":" + credentials.password)
        } : {};

        $http.get('/login/user', {headers: headers})
            .success(successFunction)
            .error(failureFunction);
    };

    service.logout = function(successFunction, failureFunction) {
        $http.post('/auth/logout', {})
            .success(successFunction)
            .error(failureFunction);
    };

    return service;
});

登录控制器

angular.module("danceSchoolManagement.authController", [])
.controller("authController", function ($rootScope, $scope, authService) {

    $scope.credentials = {};

    $scope.authenticate = function (credentials) {
        authService.authenticate(credentials,
            function (returnedData) {
                $rootScope.user = returnedData;
            }, function (returnedData) {
                $rootScope.user = null;
            });
    };

    $scope.login = function () {
        $scope.authenticate($scope.credentials);
    };

    $scope.authenticate();

    $scope.logout = function () {
        authService.logout(
            function (returnedData) {
                $rootScope.user = null;
            }, function (returnedData) {
                $rootScope.user = null;
            });
    };
});

0 个答案:

没有答案