通过 Spring Security 和 CAS 登录后,如何在非安全 JSP 页面上显示登录用户详细信息?

Posted

技术标签:

【中文标题】通过 Spring Security 和 CAS 登录后,如何在非安全 JSP 页面上显示登录用户详细信息?【英文标题】:How to show logged in user details on non-secured JSP page after login via Spring Security and CAS? 【发布时间】:2012-01-06 09:58:06 【问题描述】:

我有一个简单的网络应用示例。一些不安全的页面和一些安全的页面。

通过 Spring Security 和 CAS 登录。应用程序大部分工作正常 - 用户在请求安全资源时被定向到 CAS 登录页面,登录正常,用户被重定向回他们请求的安全页面。用户将拥有各种身份验证属性 - 可通过 Spring Security taglib 进行检查:http://www.springframework.org/security/tags - 例如:

Authentication class : 
    class   org.springframework.security.web.
    authentication.preauth.PreAuthenticatedAuthenticationToken

Authentication authorities : [ROLE_ADMIN]

Authentication name : admin-user

Authentication authenticated : true

Authentication principal : 
    org.springframework.security.core.userdetails.User@bf0d4bda:
    Username: admin-user; 
    Password: [PROTECTED]; 
    Enabled: true; 
    AccountNonExpired: true;   
    credentialsNonExpired: true; 
    AccountNonLocked: true; 
    Granted Authorities: ROLE_ADMIN

但是,一旦该登录用户访问了一个不安全的页面,他们就会被视为没有这些凭据。相反,它们被视为

Authentication class : class 
    org.springframework.security.authentication.AnonymousAuthenticationToken

Authentication authorities : [ROLE_ANONYMOUS]

Authentication name : anonymousUser

Authentication authenticated : true

Authentication principal : anonymousUser

因此,这使得无法使用安全标签库根据用户是否登录来显示或隐藏不安全页面上的页面项目 - 例如,如果用户已经登录,则无法显示注销按钮在:

<sec:authorize access="isAuthenticated()" >
    <a href='<c:url value="/j_spring_security_logout" />'>logout</a>
</sec:authorize>

如果未登录,则显示登录按钮:

<sec:authorize access="not isAuthenticated()" >
    <a href='<c:url value="/secure/home" />'>login</a>
</sec:authorize>

即使已登录,登录用户在这些页面中也始终显示为未通过身份验证。因此,始终会看到登录按钮,而永远不会看到注销。返回安全页面时,没有问题。这对我的应用程序来说并不是致命的——但同样的原则使我无法使用仅适用于登录用户的内容(菜单、消息等)来自定义非安全页面。

这是 Spring Security + CAS 的正常行为吗?或者有没有办法让它像你期望的那样工作?也许我错误地配置了过滤器链?

还有一件事 - 我已经尝试在会话中查看 SPRING_SECURITY_CONTEXT。起初我认为这会起作用 - 这会在不安全的页面上填充 Granted Authorities = ROLE_ADMIN。所以,我想我可以用它来检测用户是否登录并拥有正确的权限。但是,SPRING_SECURITY_CONTEXT 不会在从 CAS 返回时加载的第一个安全页面上填充 - 仅在后续页面加载时填充。

【问题讨论】:

请看***.com/questions/7391735/… 这有什么帮助?宠物诊所不使用 CAS。 看来我配置错误。不安全页面的过滤器链中缺少 SecurityContextPersistenceFilter。当回到非安全页面时,添加它似乎可以工作并保持登录用户角色。 我怀疑您关闭了对非安全请求的过滤器。不安全页面的过滤器链中缺少 SecurityContextPersistenceFilter 将具有相同的效果。很高兴你解决了这个问题。 【参考方案1】:

您必须告诉 Spring 会话管理器,实际上有一个用户会话并且 Spring 必须维护它。

<http use-expressions="true"
    auto-config="true"
    lowercase-comparisons="true"
    disable-url-rewriting="true"
    access-denied-page="/accessDenied.jsf"
    entry-point-ref="casAuthenticationFilterEntryPoint">
    [..]
    <custom-filter ref="concurrencyFilter" position="CONCURRENT_SESSION_FILTER" />
    <custom-filter ref="casAuthenticationFilter" position="CAS_FILTER" />

    <logout invalidate-session="true" 
        logout-success-url="$cas.url/logout?service=$local.url/workspace/" />
</http>

这是我们实现的安全过滤器链的一部分,重要的是下面定义的 concurrencyFiltercasAuthenticationFilter

<beans:bean id="casAuthenticationFilter"
    class="org.springframework.security.cas.web.CasAuthenticationFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
    <beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
    <beans:property name="sessionAuthenticationStrategy" ref="sas" />
</beans:bean>

<beans:bean id="sas"
    class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
    <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
    <beans:property name="migrateSessionAttributes" value="true" />
    <beans:property name="exceptionIfMaximumExceeded" value="true" />
    <beans:property name="alwaysCreateSession" value="true" />
    <beans:property name="maximumSessions" value="20" />
</beans:bean>

<beans:bean id="sessionRegistry"
    class="org.springframework.security.core.session.SessionRegistryImpl" />

<beans:bean id="concurrencyFilter"
    class="org.springframework.security.web.session.ConcurrentSessionFilter">
    <beans:property name="sessionRegistry" ref="sessionRegistry" />
    <beans:property name="expiredUrl" value="/sessionExpired.jsf" />
</beans:bean>

我希望这会有所帮助,并且是完整的。我现在要走了,但如果您需要更多,请询问

【讨论】:

以上是关于通过 Spring Security 和 CAS 登录后,如何在非安全 JSP 页面上显示登录用户详细信息?的主要内容,如果未能解决你的问题,请参考以下文章

Grails Spring Security 和 CAS 问题

Spring-security-cas 插件单点注销不起作用

使用 Spring Security 和 CAS 单点注销

具有 CAS 身份验证和自定义授权的 Spring Security

Web服务中的Spring Security CAS实现

使用 CAS + Spring Security 实现 SSO