我使用Spring和Spring-security 3.0.RELEASE以及jsf 1.2,richface 3.3和hibernate3。
我想避免同一个用户在差异浏览器中多次登录。我创建了一个自定义身份验证提供程序,如下所示:
public class AuthenthicationServiceProvider extends AbstractUserDetailsAuthenticationProvider {
private StaffDao staffDao ;
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
// TODO Auto-generated method stub
}
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
UserDetails ad = null;
try {
ad= getUserDetailInfo(authentication.getPrincipal().toString(), authentication.getCredentials().toString());
} catch (Exception e) {
throw new CustomAuthenticationException(e.getMessage()) ;
}
return ad;
}
private AuthUserDetail getUserDetailInfo(final String login, final String password ) throws CustomAuthenticationException{
Staff user = staffDao.getStaffByLogin(login, password);
String role = "ROLE_ADMIN";
if (null == user ) {
throw new CustomAuthenticationException("Invalid Username or password");
}
return new AuthUserDetail(user, role);
}
public StaffDao getStaffDao() {
return staffDao;
}
public void setStaffDao(StaffDao staffDao) {
this.staffDao = staffDao;
}
UserDetail如下:
public class AuthUserDetail implements UserDetails,Serializable {
private static final long serialVersionUID = -3727430377858939077L;
private Staff staff;
private String role;
private Set<GrantedAuthority> authorities;
public AuthUserDetail(Staff pstaff, String pRole){
setStaff(pstaff);
setRole(pRole);
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> a = new ArrayList<GrantedAuthority>(Arrays.asList(new GrantedAuthority(){
public String getAuthority() {
return role;
}
}));
return a;
}
@Override
public String getPassword() {
return this.staff.getPassword();
}
@Override
public String getUsername() {
return this.staff.getLoginId();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public Staff getStaff() {
return staff;
}
public void setStaff(Staff staff) {
this.staff = staff;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@Override
public boolean equals(Object rhs) {
if (!(rhs instanceof AuthUserDetail) || (rhs == null)) {
return false;
}
AuthUserDetail user = (AuthUserDetail) rhs;
// We rely on constructor to guarantee any User has non-null
// authorities
if (!getAuthorities().equals(user.getAuthorities())) {
return false;
}
// We rely on constructor to guarantee non-null username and password
return (this.getPassword().equals(user.getPassword()) && this.getUsername().equals(user.getUsername())
&& (this.isAccountNonExpired() == user.isAccountNonExpired())
&& (this.isAccountNonLocked() == user.isAccountNonLocked())
&& (this.isCredentialsNonExpired() == user.isCredentialsNonExpired())
&& (this.isEnabled() == user.isEnabled()));
}
@Override
public int hashCode() {
int code = 9792;
for (GrantedAuthority authority : getAuthorities()) {
code = code * (authority.hashCode() % 7);
}
if (this.getPassword() != null) {
code = code * (this.getPassword().hashCode() % 7);
}
if (this.getUsername() != null) {
code = code * (this.getUsername().hashCode() % 7);
}
if (this.isAccountNonExpired()) {
code = code * -2;
}
if (this.isAccountNonLocked()) {
code = code * -3;
}
if (this.isCredentialsNonExpired()) {
code = code * -5;
}
if (this.isEnabled()) {
code = code * -7;
}
return code;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(": ");
sb.append("Username: ").append(this.getUsername()).append("; ");
sb.append("Password: [PROTECTED]; ");
sb.append("Enabled: ").append(this.isEnabled()).append("; ");
sb.append("AccountNonExpired: ").append(this.isAccountNonExpired()).append("; ");
sb.append("credentialsNonExpired: ").append(this.isCredentialsNonExpired()).append("; ");
sb.append("AccountNonLocked: ").append(this.isAccountNonLocked()).append("; ");
if (!authorities.isEmpty()) {
sb.append("Granted Authorities: ");
boolean first = true;
for (GrantedAuthority auth : authorities) {
if (!first) {
sb.append(",");
}
first = false;
sb.append(auth);
}
} else {
sb.append("Not granted any authorities");
}
return sb.toString();
}
}
和安全配置:
<?xml version="1.0" encoding="UTF-8"?>
<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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<global-method-security pre-post-annotations="enabled" secured-annotations="enabled" jsr250-annotations="enabled" />
<http auto-config="true" access-denied-page="/login.xhtml">
<intercept-url pattern="/logout*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/error/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/css/**" filters="none" />
<intercept-url pattern="/images/**" filters="none" />
<intercept-url pattern="/js/**" filters="none" />
<intercept-url pattern="/a4j/**" filters="none" />
<intercept-url pattern="/common/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/customers/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/journal/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/masterCustomer/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/report/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/setting/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/staffs/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/templates/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/transactions/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/winloses/**" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_USER" />
<form-login
login-processing-url="/j_spring_security_check"
login-page="/login.xhtml"
default-target-url="/transactions/index.xhtml"
authentication-failure-url="/login.xhtml?error=true" always-use-default-target="true" />
<session-management session-authentication-error-url="/login.xhtml?expired=2" invalid-session-url="/login.xhtml?expired=1" session-fixation-protection="newSession">
<concurrency-control session-registry-ref="sessionRegistry" max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login.xhtml?errorMessage=The session is expired due to another user logging in with your user name and password."/>
</session-management>
</http>
<authentication-manager >
<authentication-provider ref="authenthicationServiceProvider" />
</authentication-manager>
<beans:bean id="authenthicationServiceProvider" class="com.cboclub.csmweb.service.AuthenthicationServiceProvider">
<beans:property name="staffDao" ref="staffDao" />
</beans:bean>
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
</beans:beans>
你有什么想法吗?