我正在使用Spring 4和Hibernate 4我实现了Spring安全性并且工作正常但是,我不想允许使用相同凭据的并发登录。 1.我已将Listener“HttpSessionEventPublisher”添加到web.xml,并在spring security中使用“Session management”标记来实现并发控制,但它不起作用以下是完整的代码:
的web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
弹簧security.xml文件
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="permitAll()" />
<intercept-url pattern="/loginError" access="isAnonymous()" />
<intercept-url pattern="/sessionTimeout" access="isAnonymous()" />
<intercept-url pattern="/forgotPassword" access="isAnonymous()" />
<intercept-url pattern="/requestNewPassword" access="isAnonymous()" />
<intercept-url pattern="/assets/**" access="permitAll()" />
<intercept-url pattern="/sessionExpired" access="isAnonymous()" />
<intercept-url pattern="/error" access="isAnonymous()" />
<form-login login-page="/login"
username-parameter="userId"
password-parameter="password"
authentication-success-handler-ref="cdatSuccessHandler"
authentication-failure-url="/loginError" />
<!-- <session-management session-fixation-protection="newSession" invalid-session-url="/sessionTimeout">
</session-management> -->
<session-management>
<concurrency-control max-sessions="1" expired-url="/sessionTimeout" />
</session-management>
<intercept-url pattern="/**" access="isAuthenticated()"/>
<csrf/>
<!-- <access-denied-handler error-page="/sessionExpired"/> -->
<headers>
<xss-protection enabled="true" block="true"/>
</headers>
</http>
<authentication-manager erase-credentials="true">
<authentication-provider ref="cdatAuthenticationProvider"> </authentication-provider>
</authentication-manager>
身份验证提供程序类
package com.component.cdat.security.configuration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import com.component.cdat.project.bean.MappProjectUser;
import com.component.cdat.user.bean.User;
import com.component.cdat.user.services.UserService;
@Component("cdatAuthenticationProvider")
public class CDATAuthenticationProvider implements AuthenticationProvider{
@Autowired
UserService userService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String loginId = authentication.getName().trim();
String password = (String) authentication.getCredentials();
if(loginId == null || password == null || loginId.isEmpty() || password.isEmpty()){
// throw exception
System.out.println("username or password is empty!!");
throw new NullPointerException();
}
User user = userService.getUserByUserName(loginId);
if(user == null || !loginId.equalsIgnoreCase(user.getUserName())){
System.out.println("User Not Found!!");
throw new NullPointerException();
}
if(!password.equalsIgnoreCase(user.getPassword())){
System.out.println("Pasword is incorrect!!");
throw new NullPointerException();
}
Collection<? extends GrantedAuthority> authorities = getAuthorities(user);
return new UsernamePasswordAuthenticationToken(user, password, authorities);
}
private Collection<? extends GrantedAuthority> getAuthorities(User user){
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
List<MappProjectUser> userAuthorityList = userService.getUserRole(user.getUserId());
for(MappProjectUser userAuthority : userAuthorityList){
authorities.add(new SimpleGrantedAuthority("ROLE_" + userAuthority.getUserType().getShortDesc()));
}
return authorities;
}
@Override
public boolean supports(Class<?> arg0) {
return true;
}
}
答案 0 :(得分:0)
查看reference documentation(这是针对spring security 3.1):
<http>
...
<session-management>
<concurrency-control max-sessions="1" />
</session-management>
</http>
这会阻止用户多次登录 - 第二次登录会导致第一次登录失效。通常您更愿意阻止第二次登录,在这种情况下您可以使用
<http>
...
<session-management>
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
</http>
尝试将error-if-maximum-exceeded="true"
添加到concurrency-control
标记,看看它是否有效。请注意这种并发控制的缺点:如果用户在没有注销的情况下关闭浏览器,他将无法在会话超时之前登录(通常是30分钟......所以他赢了但不能在接下来的30分钟内访问该网站。)