最近经常做DEMO,为节省时间,难免要拼凑(叫集成也行)不同的系统,经常遇到这样的场景,某DEMO,要集成A,B两个系统,登录A系统之后,要访问B系统的时候自动登录。其中每个待拼凑的系统毫无疑问都有各自的权限,我们第一反应是单点登录(SSO),然而搞个单点登录太麻烦,闹不好,甚至要花更多的时间, 排除掉单点登录,最多想到的是自动登录。还在以前研究过Acegi,对其中的机理有一些了解,因此改造起来还是相对简单。
访问需要自动登录的系统的时候,对该系统做一个Filter,代码如下:
public class AutoLoginFilter implements javax.servlet.Filter
{
private String password;
private String username;
private String authority;
/* (non-Javadoc)
* @see javax.servlet.Filter#destroy()
*/
@Override
public void destroy()
{
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException
{
UserDetails userDetail = new UserDetailsImpl();
UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(username,password, userDetail.getAuthorities());
result.setDetails(userDetail);
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(result);
arg2.doFilter(arg0, arg1);
}
/* (non-Javadoc)
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
@Override
public void init(FilterConfig arg0) throws ServletException
{
// TODO Auto-generated method stub
}
class UserDetailsImpl implements UserDetails
{
@Override
public boolean isEnabled()
{
return true;
}
@Override
public boolean isCredentialsNonExpired()
{
return true;
}
@Override
public boolean isAccountNonLocked()
{
return true;
}
@Override
public boolean isAccountNonExpired()
{
return false;
}
@Override
public String getUsername()
{
return username;
}
@Override
public String getPassword()
{
return password;
}
@Override
public GrantedAuthority[] getAuthorities()
{
String[] authoritys=authority.split(",");
GrantedAuthority[] grantedAuthority = new GrantedAuthority[authoritys.length];
List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
for(int i=0;i<authoritys.length;i++)
{
grantedAuthority[i]=new GrantedAuthorityImpl(authoritys[i]);
}
return grantedAuthority;
}
}
/**
* @return Returns the password.
*/
public String getPassword()
{
return password;
}
/**
* @param password The password to set.
*/
public void setPassword(String password)
{
this.password = password;
}
/**
* @return Returns the username.
*/
public String getUsername()
{
return username;
}
/**
* @param username The username to set.
*/
public void setUsername(String username)
{
this.username = username;
}
/**
* @return Returns the authority.
*/
public String getAuthority()
{
return authority;
}
/**
* @param authority The authority to set.
*/
public void setAuthority(String authority)
{
this.authority = authority;
}
}
Spring配置文件有如下两处需要修改
1、设置拦截器,此处设置访问任何路径自动登录
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,autoLoginFilter,basicProcessingFilter,filterInvocationInterceptor,switchUserProcessingFilter
</value>
</property>
</bean>
2、设置默认登录的用户名和角色,其中角色可以设置多个,并以“,”分割,当然这此应设置一个最全的权限,否则自动登录好像没什么意义
<bean id="autoLoginFilter" class="com.***.security.AutoLoginFilter">
<property name="username" value="admin"></property>
<property name="password" value="1"></property>
<property name="authority" value="ROLE_USER,ROLE_ADMINISTRATOR">
</property>
</bean>
当然,如上只是为了快速拼凑DEMO用,真实系统还是采取SSO的。