使用Spring Security在一个选项卡中注销后,将所有选项卡重定向到登录页面
目前,我在Spring安全性方面遇到了一个问题,因为当我打开两个选项卡并在其中一个选项卡中注销时,会话肯定会被破坏,但我仍然可以在另一个选项卡上执行一些操作,该选项卡应该将我重定向到登录页面,而不允许我执行任何其他操作 直到我刷新页面,它才会重定向到登录页面,因为不再有有效会话 我试图找到一个解决方案,迫使其他选项卡重定向到注销页面,而不允许用户在其他选项卡中注销时做任何其他事情 我想知道我们是否可以通过Spring安全配置实现这样的目标 下面是我的spring security.xml使用Spring Security在一个选项卡中注销后,将所有选项卡重定向到登录页面,spring,spring-security,Spring,Spring Security,目前,我在Spring安全性方面遇到了一个问题,因为当我打开两个选项卡并在其中一个选项卡中注销时,会话肯定会被破坏,但我仍然可以在另一个选项卡上执行一些操作,该选项卡应该将我重定向到登录页面,而不允许我执行任何其他操作 直到我刷新页面,它才会重定向到登录页面,因为不再有有效会话 我试图找到一个解决方案,迫使其他选项卡重定向到注销页面,而不允许用户在其他选项卡中注销时做任何其他事情 我想知道我们是否可以通过Spring安全配置实现这样的目标 下面是我的spring security.xml <
<!-- Secure token end point -->
<http pattern="/api/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- secure api service -->
<http pattern="/api/service/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/api/service/**" method="GET"
access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http auto-config="true" use-expressions="true"
xmlns="http://www.springframework.org/schema/security"
authentication-manager-ref="userAuthenticationManager">
<access-denied-handler error-page="/accessDenied" />
<intercept-url pattern="/home/**" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/index" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/pages/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/overviewOfferLetter" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/importOldCandidate" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/RecruitmentEvent" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/questionnaireResultId**" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_INTERVIEWER')"/>
<intercept-url pattern="/evaluation**" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_INTERVIEWER')"/>
<intercept-url pattern="/questionnaireResult" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_CV_SCREENER') or hasRole('ROLE_MANAGER')"/>
<intercept-url pattern="/activityLogs" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/oldCandidate" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/advancedSearch" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/listApplicants" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/duplicatedEmail" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/createApplicant" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/jobHistory" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/importOldCandidate" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/oldCandidate" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/importApplicant" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<form-login login-page="/login"
default-target-url="/index"
always-use-default-target="true"
authentication-failure-url="/login?error=incorrect"
authentication-success-handler-ref="customAuthenticationSuccessHandler"
username-parameter="username"
password-parameter="password"
/>
<logout logout-success-url="/login?logout" delete-cookies="JSESSIONID" />
</http>
<bean id="customAuthenticationSuccessHandler" class="com.axonactive.security.CustomAuthenticationSuccessHandler" />
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider ref="authenticationProvider">
</authentication-provider>
</authentication-manager>
<bean id="authenticationProvider" class="com.axonactive.security.CustomAuthenticationProvider"></bean>
<global-method-security secured-annotations="enabled"
pre-post-annotations="enabled" proxy-target-class="true"
xmlns="http://www.springframework.org/schema/security">
<expression-handler ref="expressionHandler" />
</global-method-security>
<bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator">
<bean id="permissionEvaluator" class="com.axonactive.security.AccountPermissionEvaluator" />
</property>
</bean>
<bean id="webExpressionHandler"
class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
<property name="permissionEvaluator">
<bean id="permissionEvaluator" class="com.axonactive.security.AccountPermissionEvaluator" />
</property>
</bean>
<!-- Define LDAP Service -->
<bean id="ldapService" class="com.axonactive.service.implement.LdapService">
<property name="contextFactory" value="${ldap.contextFactory}" />
<property name="url" value="${ldap.url}" />
<property name="securityAuthentication" value="${ldap.securityAuthentication}" />
<property name="username" value="${ldap.username}" />
<property name="password" value="${ldap.password}" />
<property name="searchBase" value="${ldap.searchBase}" />
<property name="searchName" value="${ldap.searchName}" />
<property name="distinguishedName" value="${ldap.distinguishedName}" />
</bean>
<!-- End LDAP Service -->
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<!-- End point filter for client -->
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<!-- Client credential authentication manager -->
<authentication-manager alias="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<!-- Declare client service -->
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetailsService" />
</bean>
<!-- Declare client list -->
<oauth:client-details-service id="clientDetailsService">
<oauth:client client-id="testSystem"
secret="9346336818f9d382a22ac5d4486fa5ee" scope="read"
authorized-grant-types="client_credentials" />
</oauth:client-details-service>
<!-- Config oauth server -->
<oauth:authorization-server
client-details-service-ref="clientDetailsService" token-services-ref="tokenServices">
<oauth:client-credentials />
</oauth:authorization-server>
<!-- Declare resource server, where the token token are store -->
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<!-- Store token in memory -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="dataSource" />
</bean>
<!-- Configuration token service , expire in one day, don't support refresh
token -->
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="false" />
<property name="accessTokenValiditySeconds" value="86400"></property>
<property name="clientDetailsService" ref="clientDetailsService" />
</bean>
如果你们需要查看任何其他文件或信息,请告诉我。正如@kryger所说,您的客户端代码需要检查您的会话是否仍然经过身份验证。我们的客户端应用程序也有类似的问题,因为Spring希望重定向未经授权的请求,但我们的客户端应用程序正在以“rest-ful”方式与服务器通信,因此客户端应用程序只是默默地向最终用户失败 我们通过使用第二个AuthenticationEntryPoint来解决此问题,特别是使用。通过使用http403forbiddennentrypoint.html,与传统的Spring安全重定向相比,客户端应用程序发出的所有未经授权的请求都会得到一个http403错误。然后,我们的客户端应用程序配置了一个拦截器来侦听任何403错误,并向用户提示登录 下面是一个示例Spring安全配置,它使用我们的WebSecurityConfigureAdapter配置中的Http403ForbiddenEntryPoint
/**
* Configures all the AuthenticationEntryPoints for our app
*/
protected DelegatingAuthenticationEntryPoint delegatingAuthenticationEntryPoint() {
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints =
new LinkedHashMap<RequestMatcher, AuthenticationEntryPoint>();
// entry point for unauthenticated client apps
entryPoints.put(new SecuredApiRequestMatcher(), new Http403ForbiddenEntryPoint());
// entry point for our normal website
DelegatingAuthenticationEntryPoint delegatingEntryPoint =
new DelegatingAuthenticationEntryPoint(entryPoints);
delegatingEntryPoint.setDefaultEntryPoint(new LoginUrlAuthenticationEntryPoint(SIGNIN_URL));
return delegatingEntryPoint;
}
/**
* {@link RequestMatcher} that checks if requested url matches a secured api path.
*/
final class SecuredApiRequestMatcher implements RequestMatcher {
final Map<String, String[]> securedMethodToUrlMap;
public SecuredApiRequestMatcher() {
securedMethodToUrlMap = new HashMap<String, String[]>();
securedMethodToUrlMap.put(GET.name(), SECURED_GET_URLS);
securedMethodToUrlMap.put(PUT.name(), SECURED_PUT_URLS);
securedMethodToUrlMap.put(POST.name(), SECURED_POST_URLS);
securedMethodToUrlMap.put(DELETE.name(), SECURED_DELETE_URLS);
}
@Override
public boolean matches(HttpServletRequest request) {
String url = UrlUtils.buildRequestUrl(request);
String method = request.getMethod();
String[] securedUrls = securedMethodToUrlMap.get(method);
if(securedUrls != null) {
for(String securedUrl : securedUrls) {
if(url.startsWith(securedUrl))
return true;
}
}
return false;
}
}
/**
*为我们的应用程序配置所有AuthenticationEntryPoints
*/
受保护的DelegatingAuthenticationEntryPoint DelegatingAuthenticationEntryPoint(){
LinkedHashMap入口点=
新建LinkedHashMap();
//未经验证的客户端应用程序的入口点
put(新的SecuredApiRequestMatcher(),新的Http403ForbiddenEntryPoint());
//我们正常网站的入口点
DelegatingAuthenticationEntryPoint delegatingEntryPoint=
新的授权验证入口点(入口点);
delegatingEntryPoint.setDefaultEntryPoint(新的LoginRuthenAuthenticationEntryPoint(登录URL));
返回delegatingEntryPoint;
}
/**
*{@link RequestMatcher}检查请求的url是否与安全的api路径匹配。
*/
最后一个类SecuredApiRequestMatcher实现RequestMatcher{
最终地图安全方法地图;
public SecuredApiRequestMatcher(){
securedMethodToUrlMap=新HashMap();
securedMethodToUrlMap.put(GET.name(),SECURED\u GET\u URL);
securedMethodToUrlMap.put(put.name(),SECURED\u put\u URL);
securedMethodToUrlMap.put(POST.name(),SECURED\u POST\u URL);
securedMethodToUrlMap.put(DELETE.name(),SECURED\u DELETE\u URL);
}
@凌驾
公共布尔匹配(HttpServletRequest){
字符串url=UrlUtils.buildRequestUrl(请求);
String方法=request.getMethod();
字符串[]securedUrls=securedMethodToUrlMap.get(方法);
if(securedUrls!=null){
用于(字符串securedUrl:securedUrls){
if(url.startsWith(securedUrl))
返回true;
}
}
返回false;
}
}
最后,这里是来自Http403ForbiddenEntryPoint的响应
{“时间戳”:1430938979916,“状态”:403,“错误”:“禁止”,“消息”:“访问”
拒绝”,“路径”:“/api/secured/url”}
客户端代码必须主动检查会话是否仍处于活动状态,如果未处于活动状态,则重定向到登录;Spring Security与此无关。正如您所说,在执行任何操作之前,我必须检查会话是否仍处于活动状态?目前,我不使用Java字节码管理任何配置,我的每个配置现在都在xml文件中。那么,您还有其他与xml文件相关的选项吗。