Tomcat 重启后 Spring Security 主体未完全填充

Posted

技术标签:

【中文标题】Tomcat 重启后 Spring Security 主体未完全填充【英文标题】:Spring Security principal isn't fully populated after Tomcat restart 【发布时间】:2011-10-13 01:23:41 【问题描述】:

我的问题简而言之,在服务器重启(我自己的本地 Tomcat)之后,Spring Security 主体对象会重新填充每个字段(用户名、密码、电子邮件、用户类型等)除了用户 ID 字段。

我有以下 User 对象,它实现了 Spring 的 UserDetails 对象并扩展了我自己的基对象类:

public class User extends BaseDomainObject implements UserDetails 
    private String username;
    private String emailAddress;
    private String password;
    // ... etc ... /

(仅供参考,User 类有一个构造函数,它接受除 ID 之外的所有字段(由 hibernate 偷偷注入)。此对象上没有设置器。不确定这是否重要。)

用户 ID 字段位于 BaseDomainObject 中:

class BaseDomainObject 
    protected Long id;
    public Long getId() 
        return id;
    

成功登录后,主体将填充上述用户详细信息(包括 ID),一切顺利。以下日志输出证实了这一点(其中包括上面 User 类的 toString 表示形式,形式为 User[id,username,emailAddress]):

2011-07-26 11:50:25,188 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@5e8fac5a: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@5e8fac5a: Principal: User[1,test,test@test.com]; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@255f8: RemoteIpAddress: 0:0:0:0:0:0:0:1%0; SessionId: 450FFF87C04098ECC58C2E0829D21D69; Granted Authorities: ROLE_USER, ROLE_CUSTOMER'

但是,在服务器重新启动后,相同的日志输出如下所示:

2011-07-26 11:52:28,355 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@729a68c9: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@729a68c9: Principal: User[null,test,test@test.com]; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@255f8: RemoteIpAddress: 0:0:0:0:0:0:0:1%0; SessionId: 450FFF87C04098ECC58C2E0829D21D69; Granted Authorities: ROLE_USER, ROLE_CUSTOMER'

我应该重申,用户类(而不是基类)上的其他字段也已成功填充。基本上除了ID之外的所有东西。

设置字段时,Spring 安全性是否调用 User 构造函数?诚然,我从来没有真正想过“如何”Spring 重新填充其他领域 - 也许这是我的问题?我真的不想在构造函数中使用 setter / 公开 ID 字段。事实上,在构造函数中添加 ID 并没有任何作用。

感谢您的帮助。

【问题讨论】:

能否粘贴自定义 userDetailService 的实现以及在安全上下文 xml 中的调用位置? 这两个类不应该实现Serializable吗?如果您想了解如何重新填充域对象,为什么不设置断点并附加调试器? groan 你说得对,matt b - UserDetails 扩展了 Serializable 但 BaseDomainObject 没有。添加 Serializable 解决了这个问题。如果您想在下面回答,我可以接受您的回答吗? 【参考方案1】:

我建议确保您的两个域对象 implements Serializable,否则 servlet 容器可能会选择不将它们序列化到磁盘(这是重新启动后重新填充会话数据的方式 - Tomcat 正在读取序列化的会话数据到一个文件)。

【讨论】:

更多细节:查看 SecurityContextPersistenceFilter 类,它定义了 SecurityContextHolder 的填充方式。如果您使用的是 HttpSessionSecurityContextRepository,则用户的安全上下文(Spring 在成功验证时分配的内容)存储在 HTTP 会话中。如果您的 servlet 容器保持会话并在重启后恢复它们,那么您应该检查那里。

以上是关于Tomcat 重启后 Spring Security 主体未完全填充的主要内容,如果未能解决你的问题,请参考以下文章

重启后Spring没有将tomcat持久会话恢复到会话注册表?

springmvc 修改方法体需要重启tomcat吗

Spring Security:服务器重启后身份验证保持不变

Spring 3.0 - 无法找到 XML 模式命名空间的 Spring NamespaceHandler [http://www.springframework.org/schema/securit

Spring 3.0 - 无法找到 XML 模式命名空间的 Spring NamespaceHandler [http://www.springframework.org/schema/securit

IntelliJ IDEA 中的 Spring Boot 项目在重启后停止工作