使用 Spring Security 的预认证/单点登录

Posted

技术标签:

【中文标题】使用 Spring Security 的预认证/单点登录【英文标题】:Pre-Authentication / Single SignOn using Spring Security 【发布时间】:2012-09-01 11:17:09 【问题描述】:

我正在开发两个 Web 应用程序,一个是服务器应用程序,另一个是客户端应用程序,两者都使用 Spring Security。我的用例是,在用户登录服务器应用程序后,用户可以从服务器应用程序中的链接访问客户端应用程序。由于用户在单击这些链接时不必再次登录(我的要求的一部分),我决定使用类似于 Single SignOn 的策略,以便将他们的身份验证信息从服务器应用程序转发到客户端应用程序。

在客户端应用程序上,我使用 Spring Security 的 RequestHeaderAuthenticationFilter 来查找由服务器应用程序设置的自定义请求标头。

    如果找到此自定义标头,我是否需要进一步验证此请求是否可信?在Spring's Pre-Authentication doc 中,RequestHeaderAuthenticationFilter 不执行任何身份验证,并假定请求来自SM_USER 属性中指定的用户。如何确保请求是真实的?

    如何使用 http 请求中的自定义标头将用户从一个应用程序发送到另一个应用程序?重定向请求不起作用,因为标头信息将丢失。转发不起作用,因为转发的请求没有通过客户端应用程序上配置的 Spring Security 过滤器,因此请求永远不会“经过身份验证”,也不会创建会话。

【问题讨论】:

关于 #2 的更多信息。当用户单击服务器应用程序中的链接时,请求被重定向到一个 Servlet(在服务器应用程序上),它将在 Spring 的 SecurityContextHolder 中查找当前用户,将用户名添加为自定义请求标头以及用户授予请求的权限,并将其转发到客户端应用程序,使用 getServletContext().getContext("/client-app").getRequestDispatcher("/").forward(...) 【参考方案1】:

由于我没有收到任何回复,因此我稍微改变了方法以实现相同的 SSO 行为。我在这里回答我自己的问题以结束此问题。

我没有使用 RequestHeaderAuthenticationFilter,而是继承了 Spring 的 AbstractPreAuthenticatedProcessingFilter,它从 HttpRequest 中检索 Principal 和 Credentials。然后我实现了一个自定义preAuthenticatedUserDetailsService,它将在加载用户详细信息之前使用服务器应用程序验证凭据。

至于 #2,我不再在初始预认证登录请求中使用自定义标头。我只是将主体(用户名)和凭据作为 url 参数附加到客户端应用程序的初始预认证“登录”请求。由于两个应用程序之间的通信是通过 SSL 保护的,我认为这应该是安全的。

这是我现在的安全配置的样子:

<b:bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<b:bean id="navigatorPreAuthFilter" class="com.example.NavigatorPreAuthenticatedProcessingFilter">
    <b:property name="authenticationManager" ref="authenticationManager" />
</b:bean>

<http auto-config="false" entry-point-ref="http403EntryPoint">

    <custom-filter position="PRE_AUTH_FILTER" ref="navigatorPreAuthFilter" />
    <session-management session-fixation-protection="newSession" />
    <logout logout-success-url="/logout" delete-cookies="JSESSIONID" />

    <intercept-url pattern="/index.jsp" access="ROLE_QUESTIONNAIRE_ASSIGNEE"/>
</http>

<b:bean id="preAuthenticatedUserDetailsService" class="com.example.NavigatorPreAuthenticatedUserDetailsService" />
<b:bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <b:property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</b:bean>

<authentication-manager alias="authenticationManager">
    <authentication-provider ref="preauthAuthProvider"/>
</authentication-manager>

【讨论】:

即使您使用 SSL,用户名和密码也会最终出现在您的 httpd 日志中。需要注意的事情。 谢谢,你提出了一个非常好的观点。我将其更改为转发,并在我进入客户端应用程序后进行重定向(无论如何我打算出于不同的目的这样做)。

以上是关于使用 Spring Security 的预认证/单点登录的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Security 的预认证/单点登录

四Spring Security使用自定义认证页面

四Spring Security使用自定义认证页面

Spring Security:外部认证和内部认证

Spring Security 实现自定义登录和认证:使用自定义的用户进行认证

五Spring Security使用数据库数据完成认证