认识安全框架acegi(3)

作者:ikon999 发布于:2008年11月14日 10:09

每个框架都有一些核心的概念,这些概念被固化为类和接口,成为框架的重要组件类。框架的管理类、操作类都在这些组件类的基础上进行操作。在进入Acegi框架的具体学习前,有必要事先了解一下这些承载Acegi框架重要概念的组件类。

首先,我们要接触是UserDetails接口,它代表一个应用系统的用户,该接口定义了用户安全相关的信息,如用户名/密码,用户是否有效等信息,你可以根据以下接口方法进行相关信息的获取:

String getUsername():获取用户名;

String getPassword():获取密码;

boolean isAccountNonExpired():用户帐号是否过期;

boolean isAccountNonLocked():用户帐号是否锁定;

boolean isCredentialsNonExpired():用户的凭证是否过期;

boolean isEnabled():用户是否处于激活状态。

当以上任何一个判断用户状态的方法都返回false时,用户凭证就被视为无效。

UserDetails还定义了获取用户权限信息的方法:GrantedAuthority[] getAuthorities()GrantedAuthority代表用户权限信息,它定义了一个获取权限描述信息(以字符串表示,如PRIV_COMMON)的方法:String getAuthority()

在未使用Acegi之前,我们可能通过类似UserCustomer等领域对象表示用户的概念,并在程序中编写相应的用户认证的逻辑。现在,你要做的一个调整是让原先这些代表用户概念的领域类实现UserDetails接口,这样,Acegi就可以通过UserDetails接口访问到用户的信息了

UserDetails可能从数据库、LDAP等用户信息资源中返回,这要求有一种机制来完成这项工作,UserDetailsService正是充当这一角色的接口。UserDetailsService接口很简单,仅有一个方法:UserDetails loadUserByUsername(String username) ,这个方法通过用户名获取整个UserDetails对象。

Authentication代表一个和应用程序交互的待认证用户,Acegi从类似于登录页面、Cookie等处获取待认证的用户信息(一般是用户名密码)自动构造Authentication实例。

Authentication可以通过Object getPrincipal()获取一个代表用户的对象,这个对象一般可以转换为UserDetails,从中可以取得用户名/密码等信息。在AuthenticationAuthenticationManager认证之前,没有任何权限的信息。在通过认证之后,Acegi通过UserDetails将用户对应的权限信息加载到Authentication中。Authentication拥有一个GrantedAuthority[] getAuthorities()方法,通过该方法可以得到用户对应的权限信息。

AuthenticationUserDetails很容易被混淆,因为两者都有用户名/密码及权限的信息,接口方法也很类似。其实AuthenticationAcegi进行安全访问控制真正使用的用户安全信息的对象,它拥有两个状态:未认证和已认证。UserDetails是代表一个从用户安全信息源(数据库、LDAP服务器、CA中心)返回的真正用户,Acegi需要将未认证的Authentication和代表真实用户的UserDetails进行匹配比较,通过匹配比较(简单的情况下是用户名/密码是否一致)后,AcegiUserDetails中的其它安全信息(如权限、ACL等)拷贝到Authentication中。这样,Acegi安全控制组件在后续的安全访问控制中只和Authentication进行交互。

由于Acegi对程序资源进行访问安全控制时,一定要事先获取和请求用户对应的AuthenticationAcegi框架必须为Authentication提供一个“寓所”,以便在需要时直接从“寓所”把它请出来,作为各种安全管理器决策的依据。

SecurityContextHolder就是Authentication容身的“寓所”,你可以通过SecurityContextHolder.getContext().getAuthenication()代码获取Authentication。细心观察一下这句代码,你会发现在SecurityContextHolderAuthentication之间存在一个getContext()中介,这个方法返回SecurityContext对象。SecurityContext这个半路杀出来的程咬金有什么特殊的用途呢?我们知道Authentication是用户安全相关的信息,请求线程其它信息(如登录验证码等)则放置在SecurityContext中,构成了一个完整的安全信息上下文。SecurityContext接口提供了获取和设置Authentication的方法:

u Authentication getAuthentication()

u void setAuthentication(Authentication authentication)

SecurityContextHolderAcegi框架级的对象,它在内部通过ThreadLocal为请求线程提供线程绑定的SecurityContext对象。这样,任何参与当前请求线程的Acegi安全管理组件、业务服务对象等都可以直接通过SecurityContextHolder.getContext()获取线程绑定的SecurityContext,避免通过方法入参的方式获取用户相关的SecurityContext

线程绑定模式对于大多数应用来说是适合的,但是应用本身会创建其它的线程,那么只有主线程可以获得线程绑定SecurityContext,而主线程衍生出的新线程则无法得到线程绑定的SecurityContextAcegi考虑到了这些不同应用情况,提供了三种绑定SecurityContext的模式:

n SecurityContextHolder.MODE_THREADLOCALSecurityContext绑定到主线程,这是默认的模式;

n SecurityContextHolder.MODE_GLOBALSecurityContext绑定到JVM中,所有线程都使用同一个SecurityContext

n SecurityContextHolder.MODE_INHERITABLETHREADLOCAL::SecurityContext绑定到主线程及由主线程衍生的线程中。

你可以通过SecurityContextHolder.setStrategyName(String strategyName)方法指定SecurityContext的绑定模式。

作者:ikon999
来源:北风技术专栏
原文链接:http://column.ibeifeng.com/51564/20081114222.shtml

( 内容完 )

添加收藏到:

您可能还对这些文章感兴趣:

  • ikon999原创:Dwr2的日志代码分析
  • Hashtable简介和使用
  • java执行脚本语言javascript
  • IP及IP段进行访问限制的代码
  • 用Flex+Lucene+s2sh开发订餐系统开发第五步:前台皮肤替换功能实现(续)
  • 蹊跷的ThreadDeath,令人郁闷的glassfish
  • 每日构建 Daily build
  • 给学习java的应届生找工作的一些建议
  • WEB高性能开发(10) - 疯狂的HTML压缩
  • 关于中国国产手机游戏
  • 没有评论, 我来评论

    小贴士:评论需要管理员审核后才会显示。请不要发布与国家法律相抵触的言论,北风网将保留追究责任的权利。
    类似“顶”、“沙发”、“支持”之类没有营养的文字,对勤劳贡献的作者来说是令人沮丧的反馈信息。
    请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
    如果您发现自己的评论没有被审核或者不见了,请参考以上三条。

    每周之星

    陈臣陈臣

    七年Java和JEE开发经验,JEE应用设计和高级架构师,拥有Sun的多项Java和J2EE方面的技能认证,多年项目经理、技术部经理的管理经验。拥有全面、扎实的Java和JEE理论知识,丰富的JEE应用开发经验。

    更多作者:

  • Adam
  • ikon999
  • jk1234
  • jk2345
  • libin_8745
  • lifengxing
  • taohuang100
  • xingkong
  • 北风
  • 呆子
  • 子晨
  • 小白
  • 张章
  • 张维亮
  • 陈臣
  • 陶宝哥
  • 风风
  • 最新内容

    推荐内容

    标签

    分类