Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Spring Security在一个选项卡中注销后,将所有选项卡重定向到登录页面_Spring_Spring Security - Fatal编程技术网

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

使用Spring Security在一个选项卡中注销后,将所有选项卡重定向到登录页面,spring,spring-security,Spring,Spring Security,目前,我在Spring安全性方面遇到了一个问题,因为当我打开两个选项卡并在其中一个选项卡中注销时,会话肯定会被破坏,但我仍然可以在另一个选项卡上执行一些操作,该选项卡应该将我重定向到登录页面,而不允许我执行任何其他操作 直到我刷新页面,它才会重定向到登录页面,因为不再有有效会话 我试图找到一个解决方案,迫使其他选项卡重定向到注销页面,而不允许用户在其他选项卡中注销时做任何其他事情 我想知道我们是否可以通过Spring安全配置实现这样的目标 下面是我的spring security.xml <

目前,我在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文件相关的选项吗。