gpt4 book ai didi

Spring Security session 并发

转载 作者:行者123 更新时间:2023-12-04 23:21:30 29 4
gpt4 key购买 nike

我有一个使用 Spring 4.0 和 Security 3.2 构建的应用程序,我想实现 session 并发,但它似乎不起作用。安全性的所有其他方面都运行良好。这是我的xml配置:
首先在我的 web.xml 中:

<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>

然后在我的security.xml中
<security:http  auto-config="false" 
use-expressions="true"
authentication-manager-ref="authManager"
access-decision-manager-ref="webAccessDecisionManager"
entry-point-ref="authenticationEntryPoint">

<security:intercept-url pattern="/agent/**" access="hasAnyRole('ROLE_AGENT')" />
<security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/public/**" access="permitAll" />
<security:intercept-url pattern="/**" access="permitAll" />

<security:session-management session-authentication-strategy-ref="sas"
invalid-session-url="/public/login.xhtml"/>

<security:logout logout-success-url="/public/login.xhtml"
invalidate-session="true"
delete-cookies="true"/>
<security:expression-handler ref="webExpressionHandler"/>

<security:custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
<security:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
</security:http>


<bean id="authenticationEntryPoint"  class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg index="0" value="/public/login.xhtml" />
</bean>

<bean id="customAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
p:defaultFailureUrl="/public/login.xhtml" />

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

<bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
<constructor-arg index="0" ref="sessionRegistry"/>
<constructor-arg index="1" value="/session-expired.htm"/>
</bean>

<bean id="myAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="sessionAuthenticationStrategy" ref="sas" />
<property name="authenticationManager" ref="authManager" />
<property name="authenticationFailureHandler" ref="customAuthenticationFailureHandler"/>
</bean>

<bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<property name="maximumSessions" value="1" />
<property name="exceptionIfMaximumExceeded" value="true" />
</bean>

<bean id="authManager" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<ref bean="myCompLdapAuthProvider"/>
<ref bean="myCompDBAuthProvider"/>
</list>
</property>
</bean>

我的 UserDetails 实现了 hashCode() 和 equals() 并且所有这些并发 session 限制都不起作用。经过一点调试 session 后,我观察到我的 session 从未在 sessionRegistry 中找到,我想这是主要原因,但我不知道为什么!
知道我在这里做错了什么吗?

附言我的调试日志中有这样的记录:
(FilterChainProxy.java:337) - /resources/images/icons/connection_on.gif at position 2 of 11 in     additional filter chain; firing Filter: 'ConcurrentSessionFilter'
(FilterChainProxy.java:337) - /resources/images/icons/connection_on.gif at position 3 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
(FilterChainProxy.java:337) - /resources/images/icons/connection_on.gif at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
(FilterChainProxy.java:337) - /resources/images/icons/connection_on.gif at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
(FilterChainProxy.java:337) - /resources/images/icons/connection_on.gif at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
(FilterChainProxy.java:337) - /resources/images/icons/connection_on.gif at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
(FilterChainProxy.java:337) - /resources/images/icons/connection_on.gif at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
(AnonymousAuthenticationFilter.java:107) - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@96cf68e: Principal: MyUserDetails [username=adrian.videanu, dn=org.springframework.ldap.core.DirContextAdapter: dn=cn=Adrian Videanu,ou=IT,ou=Organization .....

所以过滤器被调用......

更新

我可以看到 session 创建事件已发布,因为我在日志中有这一行:
(HttpSessionEventPublisher.java:66) - Publishing event: org.springframework.security.web.session.HttpSessionCreatedEvent[source=org.apache.catalina.session.StandardSessionFacade@3827a0aa]  

但我从来没有像我想的那样从 SessionRegistryImpl 中点击 registerNewSession 方法。当我最初打开登录页面时也会调用 HttpSessionEventPublisher,因为我猜那是创建 session 的时候,但是在我输入凭据并推送提交之后,不再调用 HttpSessionEventPublisher。

更新 2
作为测试,我将 SessionRegistryImpl 注入(inject)到我的一个 bean 中,以尝试访问它的一些方法:
@Named
@Scope("view")
public class UserDashboardMB implements Serializable {

private static final long serialVersionUID = 1L;

@Inject
private SessionRegistry sessionRegistry;

public void init(){

System.out.println("-- START INIT -- ");
List<Object> principals = sessionRegistry.getAllPrincipals();

System.out.println("Principals = "+principals);

for (Object p:principals){
System.out.println("Principal = "+p);
}

System.out.println("-- STOP INIT -- ");
}
}

输出是:
信息: -- 开始初始化 --
信息:校长= []
信息:--停止初始化--
所以,那里什么都没有。

更新 3
我已经用 Serge 提供的 bean 替换了“sas”bean,但它似乎仍然不起作用。我再次启用了调试器,我认为问题是在方法 doFilter() 的 UsernamePasswordAuthenticationFilter 类上,我的所有请求都没有按应有的方式处理。这是 doFilter() 的一部分:
 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

if (!requiresAuthentication(request, response)) {
chain.doFilter(request, response);

return;
}

if (logger.isDebugEnabled()) {
logger.debug("Request is to process authentication");
}

Authentication authResult;
// rest of method here
}

从我在调试器中看到的情况来看,我的请求似乎不需要 auth 和 chain.doFilter(request, response);被调用。

更新 4
我想我发现了这个问题。过滤器未按应有的方式运行,因为 filterUrl 参数不是正确的。正如我在文档中读到的:

This filter by default responds to the URL /j_spring_security_check.



但我的登录部分是使用 JSF 托管 bean 和操作实现的。现在,我的登录表单位于/public/login.xhtml 并且发布登录信息的 url 是相同的。如果我将其设置为 filterUrl 我会遇到问题,因为在初始表单渲染中也被调用,并且我有一个无限循环,因为没有设置用户/密码。
知道如何克服吗?
这就是我的 LoginManagedBean 的样子:
@Named
@Scope("request")
public class LoginMB implements Serializable {

private static final long serialVersionUID = 1L;

@Autowired
@Qualifier("authManager")
private AuthenticationManager authenticationManager;

// setters and getters

public String login(){

FacesContext context = FacesContext.getCurrentInstance();

try {
Authentication request = new UsernamePasswordAuthenticationToken(this.getUsername(), this.getPassword());
Authentication result = authenticationManager.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);

// perform some extra logic here and return protected page
return "/agent/dashboard.xhtml?faces-redirect=true";

} catch (AuthenticationException e) {
e.printStackTrace();
logger.error("Auth Exception ->"+e.getMessage());
FacesMessage fm = new FacesMessage("Invalid user/password");
fm.setSeverity(FacesMessage.SEVERITY_ERROR);
context.addMessage(null, fm);
}
return null;
}
}

最佳答案

在并发 session 管理方面,spring security 3.1 和 spring security 3.2 之间存在细微差别。

ConcurrentSessionControlStrategy现在已弃用。它检查是否超过并发 session 数并在 SessionRegistry 中注册 session 。以备将来使用。

它已在 3.2 中部分替换为 ConcurrentSessionControlAuthenticationStrategy .有效控制并发 session 数是否超过但不再注册新 session (即使 javadoc 假装:我查看了源代码以理解它!)

session 注册现在委托(delegate)给 RegisterSessionAuthenticationStrategy !因此,要使 session 并发工作,您必须同时使用两者。而3.2引用手册中的例子,有效用于bean sas一个 CompositeSessionAuthenticationStrategy包含 ConcurrentSessionControlAuthenticationStrategy , 一个 SessionFixationProtectionStrategy RegisterSessionAuthenticationStrategy !

为了使整个工作正常,您只需更换您的sas bean 类:

<bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<constructor-arg ref="sessionRegistry"/>
<property name="maximumSessions" value="1" />
<property name="exceptionIfMaximumExceeded" value="true" />
</bean>
<bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
</bean>
<bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
<constructor-arg ref="sessionRegistry"/>
</bean>
</list>
</constructor-arg>
</bean>

关于Spring Security session 并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25038189/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com