Spring 安全:记住我和会话数据
Spring Security: remember me and session data
我有对象帐户:
public class Account {
String name;
List<Car> cars;
}
我在登录期间(在自定义身份验证提供程序中)填充汽车,然后将帐户保存到会话中。然后我关闭浏览器。当我再次打开它时,对象 Account 还活着,但 cars 为空。在同一会话中保存对象属性的正确方法是什么?
这是我的 applicationContext-security.xml:
的一个片段
<http use-expressions="true"
authentication-manager-ref="authenticationManager"
auto-config="true"
create-session="ifRequired">
<intercept-url pattern="/my/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>
<intercept-url pattern="/service/**" access="hasRole('ROLE_ADMIN')"/>
<form-login
login-page="/login"
authentication-failure-handler-ref="simpleUrlAuthenticationFailureHandler"
username-parameter="j_username"
password-parameter="j_password"
default-target-url="/home"
always-use-default-target="false"/>
<logout logout-success-url="/logout" invalidate-session="true" delete-cookies="JSESSIONID"/>
<http-basic />
<remember-me key="uniqueAndSecret"
token-validity-seconds="1209600"
remember-me-cookie="edrive"
remember-me-parameter="_spring_security_remember_me"
user-service-ref="localUserService"/>
</http>
以及我如何保存帐户:
Account account = accountDao.getAccount( name, password );
HttpSession session = httpUtilities.getSession(); // session from the HttpServletRequest
account.setCars(domainUtilities.getAccountCars(account.getId()));
session.setAttribute("account", account);
Spring 安全 4.1.3.RELEASE
更新 1:我的调查表明,当我第一次登录时,帐户对象仍然存在于会话中:
account core.domain.Account@1b4e3e2
并且会话还包含:
org.springframework.security.web.csrf.DefaultCsrfToken@48662c93
SPRING_SECURITY_CONTEXT org.springframework.security.core.context.SecurityContextImpl@a2e3a7b0: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@a2e3a7b0: Principal: org.springframework.security.core.userdetails.User@1901e91c: Username: someuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 0B7153F813D8F0B943C34EF19A7271C8; Granted Authorities: ROLE_USER
下次我启动浏览器时,Tomcat 8 打开一个新会话,只有:
org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN org.springframework.security.web.csrf.DefaultCsrfToken@4555644f
SPRING_SECURITY_CONTEXT org.springframework.security.core.context.SecurityContextImpl@5d1c5848: Authentication: org.springframework.security.authentication.RememberMeAuthenticationToken@5d1c5848: Principal: org.springframework.security.core.userdetails.User@1901e91c: Username: someuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_USER
并且 - SessionId 为空。为什么?这是第二次无法访问帐户的原因吗?
问题已通过将特殊过滤器添加到标准链(在应用的 WEB-APP/web.xml 中定义)得到解决。我检查用户是否已通过身份验证且帐户是否为空 - 然后我重新加载必要的数据。
其次 - 会话 ID 为空 - 这是 create-session="ifRequired" 的问题。我将其替换为 "always",现在可以使用了。
我有对象帐户:
public class Account {
String name;
List<Car> cars;
}
我在登录期间(在自定义身份验证提供程序中)填充汽车,然后将帐户保存到会话中。然后我关闭浏览器。当我再次打开它时,对象 Account 还活着,但 cars 为空。在同一会话中保存对象属性的正确方法是什么?
这是我的 applicationContext-security.xml:
的一个片段<http use-expressions="true"
authentication-manager-ref="authenticationManager"
auto-config="true"
create-session="ifRequired">
<intercept-url pattern="/my/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>
<intercept-url pattern="/service/**" access="hasRole('ROLE_ADMIN')"/>
<form-login
login-page="/login"
authentication-failure-handler-ref="simpleUrlAuthenticationFailureHandler"
username-parameter="j_username"
password-parameter="j_password"
default-target-url="/home"
always-use-default-target="false"/>
<logout logout-success-url="/logout" invalidate-session="true" delete-cookies="JSESSIONID"/>
<http-basic />
<remember-me key="uniqueAndSecret"
token-validity-seconds="1209600"
remember-me-cookie="edrive"
remember-me-parameter="_spring_security_remember_me"
user-service-ref="localUserService"/>
</http>
以及我如何保存帐户:
Account account = accountDao.getAccount( name, password );
HttpSession session = httpUtilities.getSession(); // session from the HttpServletRequest
account.setCars(domainUtilities.getAccountCars(account.getId()));
session.setAttribute("account", account);
Spring 安全 4.1.3.RELEASE
更新 1:我的调查表明,当我第一次登录时,帐户对象仍然存在于会话中:
account core.domain.Account@1b4e3e2
并且会话还包含:
org.springframework.security.web.csrf.DefaultCsrfToken@48662c93
SPRING_SECURITY_CONTEXT org.springframework.security.core.context.SecurityContextImpl@a2e3a7b0: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@a2e3a7b0: Principal: org.springframework.security.core.userdetails.User@1901e91c: Username: someuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 0B7153F813D8F0B943C34EF19A7271C8; Granted Authorities: ROLE_USER
下次我启动浏览器时,Tomcat 8 打开一个新会话,只有:
org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN org.springframework.security.web.csrf.DefaultCsrfToken@4555644f
SPRING_SECURITY_CONTEXT org.springframework.security.core.context.SecurityContextImpl@5d1c5848: Authentication: org.springframework.security.authentication.RememberMeAuthenticationToken@5d1c5848: Principal: org.springframework.security.core.userdetails.User@1901e91c: Username: someuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_USER
并且 - SessionId 为空。为什么?这是第二次无法访问帐户的原因吗?
问题已通过将特殊过滤器添加到标准链(在应用的 WEB-APP/web.xml 中定义)得到解决。我检查用户是否已通过身份验证且帐户是否为空 - 然后我重新加载必要的数据。
其次 - 会话 ID 为空 - 这是 create-session="ifRequired" 的问题。我将其替换为 "always",现在可以使用了。