现在设置认证管理器
<!-- * set authenticationManager , an
important manager-->
<bean id="authenticationManager"
class="org.acegisecurity.providers.ProviderManager">
<property
name="providers">
<list>
<ref
bean="daoAuthenticationProvider"/>
<bean
class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property
name="key" value="anonymousUser"/>
</bean>
<bean
class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property
name="key" value="rememberMeUser"/>
</bean>
</list>
</property>
<!-- here you can set
sessionController for user can't repeat (dulplicate)-->
<property
name="sessionController"
ref="concurrentSessionController"/>
</bean> |
三种认证提供者
daoAuthenticationProvider通过数据库方式来进行认证,也可以通过配置文件实现
AnonymousAuthenticationProvider,匿名用户认证,key值必须与
anonymouseProcessingFilter的key值一样,否则无法获取匿名用户的信息.
RememberMeAuthenticationProvider通过cookie认证,key值和rememberMeServices
的key值相同,否则无法取得相应的cookie信息.
sessionController,限制同一用户的登录次数,也就是同一用户在不同httpSession
中登录的次数
<!--
set concurrentSessionControllter -->
<bean id="concurrentSessionController"
class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl">
<property
name="maximumSessions" value="1"/>
<property
name="exceptionIfMaximumExceeded" value="true"/>
<property
name="sessionRegistry" ref="sessionRegistryImpl"/>
</bean>
<!-- set sessionRegistryImpl -->
<bean id="sessionRegistryImpl"
class="org.acegisecurity.concurrent.SessionRegistryImpl"/> |
这样可以限制同一用户在不同session中的次数,sessionRegistry对用户与sessionId以map的结构进行记录,但出现的一个问题就是,在用户logout时,或者session已经invalidate或expired时,他不会移除在sessionRegistry中保存的信息,
虽然sessionRegistry也提供了removeSessionInformation(String
sessionID)这个方法.
结果就是,在下次登录的时候,认证管理器先在sessionRegistry判断有此用户没,
如果有,并超过maximumSessions,就抛出异常,并无法认证.而sessionRegistry以map
结构,并用static
final形式存放信息,在不重启服务器的情况下,用户session注销后是没办法removeSessionInformation的.
我的解决办法是,通过acegi提供的listenter,在用户session
destroy,执行removeSessionInformation.
public class HttpSessionEventListener extends
HttpSessionEventPublisher {
private static final Log logger =
LogFactory.getLog(HttpSessionEventListener.class);
@Override
public void sessionDestroyed(HttpSessionEvent
event) {
// TODO 自动生成方法存根
removeSessionRegistry(event);
super.sessionDestroyed(event);
}
/**
* romove session in sessionRegistry
* @param event
*/
private void
removeSessionRegistry(HttpSessionEvent event) {
// TODO 自动生成方法存根
HttpSession session
=event.getSession();
ServletContext sc =
session.getServletContext();
WebApplicationContext wac =
WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
if(wac == null) {
logger.info("can't
webApplication Context,maybe the key in servletContext is
different");
return
;
}
SessionRegistry
sessionRegistry = null;
try {
sessionRegistry
= (SessionRegistry) wac.getBean("sessionRegistryImpl");
} catch (BeansException e)
{
// TODO
自动生成 catch 块
logger.error("get
SessionRegistry bean error,make sure bean name
'sessionRegistryImpl' exists",e);
}
sessionRegistry.removeSessionInformation(session.getId());
}
}
}
|
缺点是:wac.getBean("sessionRegistryImpl");bean name
写死了,缺乏灵活
web.xml添加如下:
<!-- httpSessionEvent ,listener session
state -->
<listener>
<listener-class>com.runsa.components.acegi.support.HttpSessionEventListener</listener-class>
</listener> |
虽然解决了当前问题,但仍然避免不了有些用户,不通过安全退出,直接关闭浏览器,
在session没有destroy时,再次登录,也会出错.在javaeye也看到类似有人提出这样的问题,捕捉window.close()事件,利用ajax在关闭浏览器的时候,进行session.invalidate(),但是,window.close()不那么容易捕捉的吧,而且个浏览器差异也是有的。
通过db认证用户
<!-- set daoAuthenticationProvider
-->
<bean id="daoAuthenticationProvider"
class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property
name="userDetailsService" ref="hibernateDaoImpl"/>
<property name="userCache"
ref="userCache"/>
<!-- here you can set
passwordEncoder -->
</bean> |
userDetailsService,保存userContext的,也就是用户的信息和相应的权限.acegi默认提供jdbcDaoImpl的实现,这里我使用hibernate自己实现了
<!-- set hibernateDaoImpl,and you can
implements daoImpl with Hibernate for yourself
-->
<bean id="hibernateDaoImpl"
class="com.runsa.components.acegi.support.HibernateDaoImpl">
<property name="userService"
ref="usersService"/>
<property
name="usernameBasedPrimaryKey" value="false"/>
</bean> |
下边是实现的code:
public static final String
DEF_USERS_BY_USERNAME_QUERY = "SELECT new
Users(u.userName,u.userPass,u.enabled) FROM Users u WHERE userName
= ?";
public
static final String DEF_Role_BY_USERNAME_QUERY = "SELECT r.roleName
FROM Role r inner join r.userRoles ur inner join ur.users u
WHERE u.userName = ?";
private
UsersService userService;
private
String roleByUsernameQuery;
private
String rolePrefix = "";
private
String usersByUsernameQuery;
private
boolean usernameBasedPrimaryKey = true;
public HibernateDaoImpl() {
usersByUsernameQuery = DEF_USERS_BY_USERNAME_QUERY;
roleByUsernameQuery = DEF_Role_BY_USERNAME_QUERY;
}
protected void
addCustomRole(String username, List roles) {}
public
boolean isUsernameBasedPrimaryKey() {
return usernameBasedPrimaryKey;
}
@SuppressWarnings("unchecked")
public UserDetails loadUserByUsername(String
username)
throws UsernameNotFoundException, DataAccessException {
List <UserDetails>users = usersByUsername(username);
if (users.size() == 0) {
throw new UsernameNotFoundException("User not found");
}
UserDetails user = users.get(0); // contains no
GrantedAuthority[]
List dbRoles = roleByUsername(user.getUsername());
addCustomRole(user.getUsername(), dbRoles);
if (dbRoles.size() == 0) {
throw new UsernameNotFoundException("User has no
GrantedAuthority");
}
GrantedAuthority[] arrayAuths = (GrantedAuthority[])
dbRoles.toArray(new GrantedAuthority[dbRoles.size()]);
String returnUsername = user.getUsername();
if (!usernameBasedPrimaryKey) {
returnUsername = username;
}
return new User(returnUsername, user.getPassword(),
user.isEnabled(), true, true, true, arrayAuths);
}
/**
* find roles by username
* @param username
* @return
*/
@SuppressWarnings("unchecked")
private List roleByUsername(String username)
{
// TODO 自动生成方法存根
roleByUsernameQuery=DEF_Role_BY_USERNAME_QUERY;
List roleList =
userService.findByParam(roleByUsernameQuery,username);
List <GrantedAuthorityImpl>roles = new
Vector();
for (Iterator
iter = roleList.iterator(); iter.hasNext();) {
String
role = (String) iter.next();
String
roleName = rolePrefix + role;
GrantedAuthorityImpl
grantedAuth =new GrantedAuthorityImpl(roleName);
roles.add(grantedAuth);
}
return roles;
}
/**
* find users by username
* @param username
* @return
*/
@SuppressWarnings("unchecked")
private List usersByUsername(String username)
{
// TODO 自动生成方法存根
List userList =
userService.findByParam(usersByUsernameQuery,username);
List <UserDetails>users =new
Vector();
for (Iterator iter = userList.iterator();
iter.hasNext();) {
Users user =
(Users) iter.next();
UserDetails
userDetails = new User(user.getUserName(), user.getUserPass(),
user.isEnabled(),
true,
true, true, new GrantedAuthority[] {new
GrantedAuthorityImpl("HOLDER")});
users.add(userDetails);
}
return users;
}
|
主要实现的方法public UserDetails loadUserByUsername(String
username)通过用户名查询用户资料,然后再通过用户用查询用户的具有角色(权限).
也可以设置passwordEncoder对密码加密,acegi提供md5,sha,等好几种加密方式.
显然,在这里认证设置了加密方式,在获取用户信息的时候,对用户的密码也需要相同的加密方式.
acegi的资源文件默认提供E文的,要自己实现本地化
<!-- set load message
resource -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename"
value="/WEB-INF/classes/messages_zh"/>
</bean> |
下边设置资源从数据库获取,并实现动态更新
<!-- * set
filterDefinitionSource for myself -->
<bean id="filterDefinitionSource"
class="com.runsa.components.acegi.inteceptor.web.DBFilterInvocationDefinationSource">
<property
name="convertUrlToLowercaseBeforeComparison"
value="true"/>
<property name="useAntPath"
value="true"/>
<property
name="acegiCacheManager" ref="acegiCacheManager"/>
</bean> |
....next page
分享到:
相关推荐
### acegi+SSH动态实现基于角色的权限管理 在企业级应用开发中,权限管理和用户认证是必不可少的安全机制。本文将详细介绍如何利用Acegi安全框架(现称为Spring Security)结合SSH(Struts + Spring + Hibernate)...
Acegi(现已被Spring Security替代)是一个强大的安全框架,可以与Spring、Hibernate和Struts 2等其他技术结合,实现基于角色的权限控制(Role-Based Access Control, RBAC)。这篇文档将探讨如何使用Acegi,以及SSH...
《SSH+Extjs4.0实现的权限管理系统:基于角色的权限设计》 在IT行业中,权限管理系统是保障系统安全性和数据隐私的关键组件。本文将深入探讨如何利用SSH(Spring、Struts2、Hibernate)框架结合Extjs4.0前端库,...
通过基于角色的权限控制,我们可以有效地管理用户的访问权限,提高系统的整体安全性。虽然Acegi Security已不再维护,但其思想和模式在现代的Spring Security中得到了延续和增强,继续为开发者提供安全框架的支持。
通过配置Spring Security,可以实现基于角色的访问控制,限制不同角色用户的操作范围。同时,这些权限信息可以在Velocity模板中动态地显示或隐藏相应的内容。 【数据库自动生成】 在开发过程中,有时需要快速生成...
Acegi Security System for Spring(简称Acegi)是Spring框架的一个扩展,它为Spring应用程序提供了全面的安全管理解决方案。在本示例中,我们将深入探讨如何将Acegi与Struts、Hibernate(SSH)这三大主流Java Web...
在权限管理方面,Spring的Acegi安全模块(现已被Spring Security取代)可以用来实现用户的认证和授权。 Hibernate3是一个持久化框架,用于简化Java对象与数据库之间的映射关系。在这个系统中,Hibernate可能是用来...
Spring Security可以与Hibernate配合,通过JDBC或ORM方式进行数据访问,实现用户、角色和权限的动态加载和管理。 在权限管理中,用户角色是一组预定义的权限集合,用户被赋予不同的角色,从而获得相应的操作权限。...
在本场景中,"ssh写的用户登录权限实现"指的是使用SSH协议来控制用户登录的权限,确保在同一时间只有一个用户能够使用特定的账号登录系统。这种机制可以防止未经授权的并发登录,增加系统的安全性。 Struts2、...
在SSH框架下,这部分功能可以通过Spring Security(原名Acegi Security)来实现,它可以提供角色和权限的管理,以及基于URL的访问控制。 在给定的压缩包文件中,"work 20120114 1426.sql"可能是数据库的备份文件,...
这个标题"ssh集成的实现了权限,员工部门"表明我们将探讨如何在这个SSH框架中实现权限管理和员工部门管理。 **Struts2** 是一个MVC(模型-视图-控制器)框架,它负责处理用户请求,控制应用程序流程,并将数据传递...
而"增、改角色信息,编辑角色权限"则涉及到角色管理和权限分配。每个用户可以被分配一个或多个角色,这些角色定义了用户在系统中的权限集合。通过角色,我们可以实现批量的权限分配,使得权限管理更为便捷。 在文件...
在权限管理中,Spring提供了强大的安全性支持,如Spring Security(原Acegi),可以实现用户的认证与授权,包括基于角色的访问控制(RBAC)和细粒度的权限分配。 Struts作为MVC框架,负责处理HTTP请求并将其映射到...
在SSH2框架下,这种设计可以充分利用Spring的安全管理功能,如Spring Security(原Acegi Security),它提供了一套完整的权限控制机制,包括认证、授权、访问控制等功能。通过配置Spring Security,可以实现用户登录...
**权限管理**:在SSH框架中,通常会利用Spring Security(原Acegi)或者Apache Shiro来实现权限控制。这些安全框架提供了角色、权限的概念,可以对用户的访问权限进行精细化控制,确保系统安全。 **文件上传下载**...
在这个“基于SSH基础的用户管理”项目中,我们主要关注的是如何使用SSH框架来实现Java中的用户管理和权限控制。SSH在这里指的是Spring、Struts和Hibernate这三个开源Java框架的组合,它们共同构建了企业级应用的基础...
7. **安全控制**:SSH框架提供了安全控制机制,例如使用Spring Security(原Acegi)进行身份验证和授权,防止未授权访问。此外,Struts2的拦截器也可以用来实现登录检查和会话管理。 8. **数据访问对象(DAO)**:...
6. **权限控制**:SSH框架支持基于角色的访问控制(RBAC),在酒店系统中,不同角色(如管理员、普通用户)有不同的操作权限,需要通过Spring Security或Acegi等扩展实现。 7. **异常处理**:系统应有完善的异常...
在权限管理中,Spring Security(以前称为Acegi Security)可以提供用户认证和授权,确保只有具备相应权限的用户才能访问特定资源。 2. Struts:Struts作为MVC(Model-View-Controller)框架的一部分,负责处理HTTP...
在本节Java SSH权限系统开发视频教程第16讲中,我们将深入探讨如何构建和实现一个基于SSH(Spring、Struts2和Hibernate)框架的安全权限管理系统。SSH是Java Web开发中常用的三大开源框架,它们各自负责不同的职责:...