Java 如何在关闭浏览器窗口时删除HttpOnly服务器端会话cookie
我需要在用户关闭浏览器窗口时关闭由Java 如何在关闭浏览器窗口时删除HttpOnly服务器端会话cookie,java,typescript,cookies,spring-security,angularjs-1.7,Java,Typescript,Cookies,Spring Security,Angularjs 1.7,我需要在用户关闭浏览器窗口时关闭由JSESSIONIDcookie持有的会话。 此cookie由Spring Security在服务器端设置: @Configuration @EnableWebSecurity public class SpringSecurityConfiguration { @Configuration public static class ApplicationApiSecurityConfiguration extends WebSecurityCo
JSESSIONID
cookie持有的会话。
此cookie由Spring Security在服务器端设置:
@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,通过设置@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
});
}
]);
}
当前,有一个注销功能,它基于通过执行此操作重定向页面。$window.location.href='logout'
但我想要的是在浏览器窗口关闭时通过单击[x]删除会话cookie(或者以某种方式使会话无效),这样即使用户通过在地址栏中粘贴URL返回到同一页面,也会要求他重新登录
问题在于
JSESSIONID
cookie被设置为HttpOnly,因此无法从JavaScript中删除。我不知道如何让服务器端的Spring Security使会话无效。回答我自己的问题
我发现在浏览器窗口关闭时实现会话过期的唯一方法是对globalUnlockHandler
onbeforeuload事件侦听器中的注销URL执行同步XHR请求
AngularJS$http.get
可能不起作用,因为它是异步的,调用在完成之前被取消
以下是传统跨浏览器XHR对象创建的TypeScript示例:
createXMLHttpRequest(): XMLHttpRequest {
var req: XMLHttpRequest = null;
if (this.$window.XMLHttpRequest) {
try {
req = new XMLHttpRequest();
} catch (e) { }
} else if (this.$window.ActiveXObject) {
try {
req = new ActiveXObject('Msxml2.XMLHTTP'); // tslint:disable-line
} catch (e) {
try {
req = new ActiveXObject('Microsoft.XMLHTTP'); // tslint:disable-line
} catch (e) { }
}
} // fi
if (!req) {
console.warn('createXMLHttpRequest() failed');
}
return req;
}
然后打电话:
var xhr = new XMLHttpRequest();
if (xhr) {
xhr.open('GET', 'http://www.domain.name/logout', false);
try {
xhr.send(null);
} catch (e) {
console.warn(e);
}
}
请注意,XHR已被弃用,而且这种方法违反了HTTP原则,因为用户可以打开一个新的浏览器选项卡并从现有浏览器复制/粘贴URL。然后,如果第一个选项卡关闭,会话将终止,但第二个选项卡仍将打开,没有有效会话。回答我自己的问题 我发现在浏览器窗口关闭时实现会话过期的唯一方法是对
globalUnlockHandler
onbeforeuload事件侦听器中的注销URL执行同步XHR请求
AngularJS$http.get
可能不起作用,因为它是异步的,调用在完成之前被取消
以下是传统跨浏览器XHR对象创建的TypeScript示例:
createXMLHttpRequest(): XMLHttpRequest {
var req: XMLHttpRequest = null;
if (this.$window.XMLHttpRequest) {
try {
req = new XMLHttpRequest();
} catch (e) { }
} else if (this.$window.ActiveXObject) {
try {
req = new ActiveXObject('Msxml2.XMLHTTP'); // tslint:disable-line
} catch (e) {
try {
req = new ActiveXObject('Microsoft.XMLHTTP'); // tslint:disable-line
} catch (e) { }
}
} // fi
if (!req) {
console.warn('createXMLHttpRequest() failed');
}
return req;
}
然后打电话:
var xhr = new XMLHttpRequest();
if (xhr) {
xhr.open('GET', 'http://www.domain.name/logout', false);
try {
xhr.send(null);
} catch (e) {
console.warn(e);
}
}
请注意,XHR已被弃用,而且这种方法违反了HTTP原则,因为用户可以打开一个新的浏览器选项卡并从现有浏览器复制/粘贴URL。然后,如果第一个选项卡关闭,会话将终止,但第二个选项卡仍将在没有有效会话的情况下打开。我有点困惑,JSESSIONID不是会话cookie吗,这意味着一旦浏览器关闭,它将被删除?可能您正在寻找类似AFAIR会话cookie的内容。重新启动浏览器后,会话cookie会暂时消失。但是,在用户注销之前,会话仍处于活动状态。浏览器窗口关闭时,JSESSION cookie不会消失。这可以通过Firefox本地存储检查器进行验证。我不知道为什么Spring在注销时在
deleteCookie()
之上有clearAuthentication()
和invalidateHttpSession()
方法。我不需要特别对JSESSION cookie做什么,我需要的是会话在窗口关闭时完全消失,不管怎样。>JSESSION cookie不会消失,只是在这里检查一下。首先,所有Firefox窗口都关闭了吗?第二,当您关闭然后重新打开时,cookie中的JSESSIONID值是否相同?第三,cookie上的expires字段是什么意思?如果它显示“会话”,那么浏览器应该在进程终止后删除它。至于您关于使会话无效的评论,您必须以某种方式将自己附加到窗口关闭事件,并对服务进行HTTP调用以注销用户。不确定Javascript是否可以做到这一点。@jzheaux由于我怀疑是Spring SessionFixationProtectionStrategy而导致JSSessionID更改。将其设置为“无”可能会起作用,但我还没有测试。在卸载事件处理期间执行对注销页面的HTTP调用也可能是一种解决方案。我明天要考试。谢谢。我有点困惑,JSESSIONID不是一个会话cookie吗,这意味着一旦浏览器关闭它就会被删除?可能您正在寻找类似AFAIR会话cookie的内容。重新启动浏览器后,会话cookie会暂时消失。但是,在用户注销之前,会话仍处于活动状态。浏览器窗口关闭时,JSESSION cookie不会消失。这可以通过Firefox本地存储检查器进行验证。我不知道为什么Spring在注销时在deleteCookie()
之上有clearAuthentication()
和invalidateHttpSession()
方法。我不需要特别对JSESSION cookie做什么,我需要的是会话在窗口关闭时完全消失,不管怎样。>JSESSION cookie不会消失,只是在这里检查一下。首先,所有Firefox窗口都关闭了吗?第二,当您关闭然后重新打开时,cookie中的JSESSIONID值是否相同?第三,cookie上的expires字段是什么意思?如果它显示“会话”,那么浏览器应该在进程终止后删除它。至于您关于使会话无效的评论,您必须以某种方式将自己附加到窗口关闭事件,并对服务进行HTTP调用以注销用户。不确定Javascript是否可以做到这一点。@jzheaux由于我怀疑是Spring SessionFixationProtectionStrategy而导致JSSessionID更改。将其设置为“无”可能会起作用,但我还没有测试。在卸载事件处理期间执行对注销页面的HTTP调用也可能是一种解决方案。我明天要考试。谢谢