使用Spring Security在一个选项卡中注销后,将所有选项卡重定向到登录页面

时间:2015-05-06 10:14:43

标签: spring spring-security

目前,我遇到了Spring Security的问题,因为当我打开两个选项卡并在一个选项卡中注销时,会话肯定会被销毁,但我仍然可以在另一个选项卡上执行某些操作,该选项卡应该重定向我登录页面,而不是让我到目前为止做任何其他行动。

直到我刷新页面,它才会重定向到登录页面,因为没有有效的会话。

我正在尝试找到一个解决方案,强制其他标签重定向到注销页面,而不会让用户在其他选项卡中注销时执行任何其他操作。

我想知道我们是否可以使用Spring Security配置实现这样的功能?

以下是我的 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>

如果您需要查看其他任何文件或信息,请告诉我。

1 个答案:

答案 0 :(得分:0)

正如@kryger所说,您的客户端代码需要检查您的会话是否仍然经过身份验证。我们的客户端应用程序遇到了类似的问题,因为Spring希望重定向未经授权的请求,但我们的客户端应用程序正在与我们的服务器进行通信,以及#34; rest-ful&#34;因此,客户端应用程序只是默默地向最终用户失败。

我们通过第二个AuthenticationEntryPoint解决了这个问题,特别是Http403ForbiddenEntryPoint。通过使用Http403ForbiddenEntryPoint.html,我们的客户端应用程序的所有未经授权的请求都会获得HTTP 403错误与传统的Spring安全重定向相比。然后我们的客户端应用程序配置了一个拦截器来监听任何403错误并提示用户注册。

以下是使用WebSecurityConfigurerAdapter配置中的Http403ForbiddenEntryPoint的Spring Security配置示例。

/**
 * 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;
    }
}

最后,这里是来自Http403ForbiddenEntryPoint的回复

  

{&#34;时间戳&#34;:1430938979916,&#34;状态&#34;:403,&#34;错误&#34;:&#34;禁止&#34;&#34;消息&# 34;:&#34;访问   否认&#34;&#34;路径&#34;:&#34; / API /固定/ URL&#34;}