在同一个 war 中防止 spring 会话覆盖
Prevent spring session override in the same war
假设我有一个 WAR,它在 JSP 中有一个前端,并且包含一个带有 REST API.
的 JAR
我有一个 spring-security.xml
,其中配置了多个 authenticationProvider。
我遇到的问题如下:
- 用户 (user1) 通过基本身份验证 (localhost/app1) 登录到 JSP-前端
- 在同一个浏览器上,不同的用户 (user2) 使用 oauth 令牌 (localhost/app2) 登录到不同的前端
- 只要此令牌用于 REST 调用 (localhost/rest),来自 JSP-前端 (app1) 的用户 (user1) 就会被 user2 覆盖。
对于 REST API,create-session="never"
已启用。但是来自 JSP 会话的用户无论如何都会被覆盖。
我正在使用 Spring 3.2.15 和 Spring 安全 3.2.9
spring-security.xml
的相关部分:
<!-- The configuration for the rest-api -->
<security:http pattern="/rest/**" create-session="never" use-expressions="true"
entry-point-ref="authenticationEntryPoint">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/rest/**" access="permitAll" method="OPTIONS" />
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
<security:custom-filter ref="CORSFilter" position="FIRST" />
<security:custom-filter ref="um-rest-resource-server" before="PRE_AUTH_FILTER" />
</security:http>
<!-- Other configration for the other endpoints (not under /rest/) ... -->
<oauth2:resource-server id="um-rest-resource-server" resource-id="um-rest-resource-server" token-services-ref="tokenVerifier" />
<bean id="tokenVerifier" class="be.healthconnect.iam.oauth2.verifier.TokenVerifier"></bean>
如果所有前端都在同一个 war 中,这就是预期的结果。
但是你可以给一个机会。如果您的 REST app2 实际上是完全无状态的,请尝试以这种方式将创建会话策略设置为无状态:create-session="stateless"
.
将会话创建策略设置为无状态时,SecurityContextHolder
甚至不会检查以查找有效会话,也不会调用它来保存成功的身份验证。
您的浏览器必须将所有请求的会话 cookie 发送到您的服务器。您的第二次调用(对 localhost/app2
)包含会话 cookie,并且 Spring 安全使用此会话(并更改您的用户)。
有一些解决方案,但如果您根本不需要会话,您可以通过设置 create-session="stateless"
告诉 Spring 安全忽略请求中的会话 cookie,请参阅 Spring Security Reference :
create-session Controls the eagerness with which an HTTP session is created by Spring Security classes. Options include:
always
- Spring Security will proactively create a session if one does not exist.
ifRequired
- Spring Security will only create a session only if one is required (default value).
never
- Spring Security will never create a session, but will make use of one if the application does.
stateless
- Spring Security will not create a session and ignore the session for obtaining a Spring Authentication
.
如果您需要会话,其他解决方案是:
- 单独的浏览器会话
- 分开WAR个文件
- URL 重写会话 ID
- 不允许再次登录
假设我有一个 WAR,它在 JSP 中有一个前端,并且包含一个带有 REST API.
的 JAR我有一个 spring-security.xml
,其中配置了多个 authenticationProvider。
我遇到的问题如下:
- 用户 (user1) 通过基本身份验证 (localhost/app1) 登录到 JSP-前端
- 在同一个浏览器上,不同的用户 (user2) 使用 oauth 令牌 (localhost/app2) 登录到不同的前端
- 只要此令牌用于 REST 调用 (localhost/rest),来自 JSP-前端 (app1) 的用户 (user1) 就会被 user2 覆盖。
对于 REST API,create-session="never"
已启用。但是来自 JSP 会话的用户无论如何都会被覆盖。
我正在使用 Spring 3.2.15 和 Spring 安全 3.2.9
spring-security.xml
的相关部分:
<!-- The configuration for the rest-api -->
<security:http pattern="/rest/**" create-session="never" use-expressions="true"
entry-point-ref="authenticationEntryPoint">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/rest/**" access="permitAll" method="OPTIONS" />
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
<security:custom-filter ref="CORSFilter" position="FIRST" />
<security:custom-filter ref="um-rest-resource-server" before="PRE_AUTH_FILTER" />
</security:http>
<!-- Other configration for the other endpoints (not under /rest/) ... -->
<oauth2:resource-server id="um-rest-resource-server" resource-id="um-rest-resource-server" token-services-ref="tokenVerifier" />
<bean id="tokenVerifier" class="be.healthconnect.iam.oauth2.verifier.TokenVerifier"></bean>
如果所有前端都在同一个 war 中,这就是预期的结果。
但是你可以给一个机会。如果您的 REST app2 实际上是完全无状态的,请尝试以这种方式将创建会话策略设置为无状态:create-session="stateless"
.
将会话创建策略设置为无状态时,SecurityContextHolder
甚至不会检查以查找有效会话,也不会调用它来保存成功的身份验证。
您的浏览器必须将所有请求的会话 cookie 发送到您的服务器。您的第二次调用(对 localhost/app2
)包含会话 cookie,并且 Spring 安全使用此会话(并更改您的用户)。
有一些解决方案,但如果您根本不需要会话,您可以通过设置 create-session="stateless"
告诉 Spring 安全忽略请求中的会话 cookie,请参阅 Spring Security Reference :
create-session Controls the eagerness with which an HTTP session is created by Spring Security classes. Options include:
always
- Spring Security will proactively create a session if one does not exist.ifRequired
- Spring Security will only create a session only if one is required (default value).never
- Spring Security will never create a session, but will make use of one if the application does.stateless
- Spring Security will not create a session and ignore the session for obtaining a SpringAuthentication
.
如果您需要会话,其他解决方案是:
- 单独的浏览器会话
- 分开WAR个文件
- URL 重写会话 ID
- 不允许再次登录