У меня есть требование закрыть сеанс, который проводит JSESSIONID
cook ie, когда пользователь закрывает окно браузера. Spring Cook: этот повар ie устанавливается на стороне сервера:
@Configuration
@EnableWebSecurity
public class SpringSecurityConfiguration {
@Configuration
public static class ApplicationApiSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) {
http
.antMatcher("/**")
.csrf()
.disable() // Disable Cross Site Request Forgery Protection
.formLogin() // Enable form based/cookie based/session based login
.loginPage(LOGIN_PAGE) // Set our custom login page
.and()
.authorizeRequests()
.antMatchers("/login", "/logout")
.permitAll() // Allow anyone to access the login and logout page
.anyRequest()
.authenticated() //All other request require authentication
.and()
.logout()
.deleteCookies("JSESSIONID") // Delete JSESSIONID cookie on logout
.clearAuthentication(true) // Clean authentication on logout
.invalidateHttpSession(true); // Invalidate Http Session on logout
}
}
}
На стороне клиента у меня есть AngularJS 1.7 и TypeScript, и я уже перехватываю событие beforeunload
, установив up @module.ts
module app.myapp {
import IModule = angular.IModule;
import IStateProvider = angular.ui.IStateProvider;
import IUrlRouterProvider = angular.ui.IUrlRouterProvider;
import LockService = lib.common.LockService;
export class MyApp {
static NAME = 'app.myapp';
static module(): IModule {
return angular.module(MyApp.NAME);
}
}
angular.module(MyApp.NAME, ['ui.router'])
.config([
'$stateProvider', '$urlRouterProvider',
($stateProvider: IStateProvider, $urlRouterProvider: IUrlRouterProvider) => {
$urlRouterProvider.when('', '/home');
$stateProvider.state('base', {
url: '',
abstract: true,
template: '<ui-view/>',
resolve: {
initEventListenerForGlobalUnlock: [
LockService.ID,
(lockService: LockService) => lockService.initListenerForGlobalUnlock()
]
}
});
$stateProvider.state('personalProfile', {
url: '/profile',
parent: 'base',
component: PersonalProfile.ID
});
}
]);
}
и затем для моей реализации LockService:
module lib.common {
import IWindowService = angular.IWindowService;
import IRootScopeService = angular.IRootScopeService;
export class LockService {
static ID = 'lockService';
static $inject: string[] = ['$window', '$rootScope'];
constructor(
private readonly $window: IWindowService,
private readonly $rootScope: IRootScopeService
) { }
private readonly globalUnlockHandler = (ev: BeforeUnloadEvent) => {
// This does not work with HttpOnly cookies
document.cookie = 'JSESSIONID=;path=/;domain=' + window.location.hostname + ';expires=Thu, 01 Jan 1970 00:00:01 GMT';
this.$rootScope.$digest();
return null;
}
/**
* This is called upon app initialisation,
* an event listener for browser close is registered,
* which will use an API call to unlock all locked sections before exiting
*/
initListenerForGlobalUnlock(): void {
this.$window.addEventListener('beforeunload', this.globalUnlockHandler);
}
}
LibCommon.module().service(LockService.ID, LockService);
}
В настоящее время существует функция выхода из системы, основанная на перенаправлении страницы с помощью this.$window.location.href = 'logout'
Но я хочу удалить сессионный повар ie (или как-то лишить законной силы сеанс), когда окно браузера закрыто, нажав [x] , чтобы даже если пользователь вернулся на той же странице, вставив URL-адрес в адресную строку, и его просят снова войти в систему.
Проблема в том, что JSESSIONID
cook ie имеет значение HttpOnly и поэтому не может быть удалено из * 1028. *. И я не знаю, как сказать Spring Security на стороне сервера, чтобы сделать сеанс недействительным.