我正在使用教程来描述如何使用
Spring Boot,Spring Security和AngularJS编写简单的单页应用程序:
https://spring.io/guides/tutorials/spring-security-and-angular-js/
我无法注销当前登录的用户 – 当我执行POST请求到“/ logout”时,我得到“404 not found” – 来自Google Chrome调试器的屏幕:
为什么要GET?我进行了POST.为什么“/ login?logout”,而不是“/ logout”?以下是用户单击注销按钮时调用的代码:
$scope.logout = function() { $http.post('logout',{}).success(function() { $rootScope.authenticated = false; $location.path("/"); }).error(function(data) { console.log("logout Failed") $rootScope.authenticated = false; }); }
春天代码:
@SpringBootApplication @RestController public class UiApplication { @RequestMapping("/user") public Principal user(Principal user) { return user; } @RequestMapping("/resource") public Map<String,Object> home() { Map<String,Object> model = new HashMap<String,Object>(); model.put("id",UUID.randomUUID().toString()); model.put("content","Hello World"); return model; } public static void main(String[] args) { SpringApplication.run(UiApplication.class,args); } @Configuration @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic().and().authorizeRequests() .antMatchers("/index.html","/home.html","/login.html","/").permitAll().anyRequest() .authenticated().and().csrf() .csrfTokenRepository(csrfTokenRepository()).and() .addFilterAfter(csrfHeaderFilter(),CsrfFilter.class); } private Filter csrfHeaderFilter() { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws ServletException,IOException { CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class .getName()); if (csrf != null) { Cookie cookie = WebUtils.getCookie(request,"XSRF-TOKEN"); String token = csrf.getToken(); if (cookie == null || token != null && !token.equals(cookie.getValue())) { cookie = new Cookie("XSRF-TOKEN",token); cookie.setPath("/"); response.addCookie(cookie); } } filterChain.doFilter(request,response); } }; } private CsrfTokenRepository csrfTokenRepository() { HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); repository.setHeaderName("X-XSRF-TOKEN"); return repository; } } }
整个AngularJS代码:
angular.module('hello',[ 'ngRoute' ]).config(function($routeProvider,$httpProvider) { $routeProvider .when('/',{templateUrl : 'home.html',controller : 'home' }) .when('/login',{ templateUrl : 'login.html',controller : 'navigation' }) .otherwise('/'); $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; }).controller('navigation',function($rootScope,$scope,$http,$location,$route) { $scope.tab = function(route) { return $route.current && route === $route.current.controller; }; var authenticate = function(credentials,callback) { var headers = credentials ? { authorization : "Basic " + btoa(credentials.username + ":" + credentials.password) } : {}; $http.get('user',{ headers : headers }).success(function(data) { if (data.name) { $rootScope.authenticated = true; } else { $rootScope.authenticated = false; } callback && callback($rootScope.authenticated); }).error(function() { $rootScope.authenticated = false; callback && callback(false); }); } authenticate(); $scope.credentials = {}; $scope.login = function() { authenticate($scope.credentials,function(authenticated) { if (authenticated) { console.log("Login succeeded") $location.path("/"); $scope.error = false; $rootScope.authenticated = true; } else { console.log("Login Failed") $location.path("/login"); $scope.error = true; $rootScope.authenticated = false; } }) }; $scope.logout = function() { $http.post('logout',{}).success(function() { $rootScope.authenticated = false; $location.path("/"); }).error(function(data) { console.log("logout Failed") $rootScope.authenticated = false; }); } }).controller('home',function($scope,$http) { $http.get('/resource/').success(function(data) { $scope.greeting = data; }) });
我是春天的新手.这是教程中的全部代码 – 也不起作用:
https://github.com/dsyer/spring-security-angular/tree/master/single
实际上你需要的只是添加一个注销成功处理程序
@Component public class logoutSuccess implements logoutSuccessHandler { @Override public void onlogoutSuccess(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Authentication authentication) throws IOException,ServletException { if (authentication != null && authentication.getDetails() != null) { try { httpServletRequest.getSession().invalidate(); // you can add more codes here when the user successfully logs // out,// such as updating the database for last active. } catch (Exception e) { e.printStackTrace(); e = null; } } httpServletResponse.setStatus(HttpServletResponse.SC_OK); } }
并在安全配置中添加成功处理程序
http.authorizeRequests().anyRequest().authenticated().and().logout().logoutSuccessHandler(logoutSuccess).deleteCookies("JSESSIONID").invalidateHttpSession(false).permitAll();