Linux安全网 - Linux操作系统_Linux 命令_Linux教程_Linux黑客

会员投稿 投稿指南 本期推荐:
搜索:
您的位置: Linux安全网 > Linux集群 > Architecture > » 正文

总结Spring Security

来源: 未知 分享至:

总结Spring Security之 关于Authentication

前言
开始花了两三天的时间学Spring Security,还是云山雾罩的,大受打击。于是重新总结一下,飞越迷雾,梳理思路,写这样一篇文字。网上有个雷锋写了Spring Security2 学习精讲:http://www.javaeye.com/topic/319965里面包含可以运行的代码,如果你对spring scurity感兴趣,可以快速浏览一下下面的笔记,然后debug code,然后再看看笔记。Spring Security的内容远比笔记复杂,我只是根据自己的理解挑重要的记录并整理一下。把sample code也当作笔记的一部分,那个code还是比较精简地,更重要的是实用。
官方提供的sample code包居然没有源代码,faint, google半天找到http://grepcode.com/snapshot/repo1.maven.org/maven2/org.springframework.security/spring-security-samples-contacts/2.0.0 当然,如果你会用git的话也可以自己check out code, 不过我没用过git这种高级货。

正文
跟权限有关的两个概念是 认证 和 授权, 先上个图:

\"image\"

Run-As Manager 和 After-Invocation Manager不重要

The actual implementation of a security interceptor will depend on what resource is being secured. If you’re securing a URL in a web application, the security interceptor will be implemented as a servlet filter. But if you’re securing a method invocation, aspects will be used to enforce security.

这篇只说Authentication Manager:

认证是通过AuthenticationManager来管的,

public interface AuthenticationManager {
public Authentication authenticate(Authentication authentication)
throws AuthenticationException;

}

The authenticate() method will attempt to authenticate the user using the org.acegisecurity.Authentication object (which carries the principal and credentials). If successful, the authenticate() method returns a complete Authentication object, including information about the user’s granted authorities (which will be considered by the authorization manager).

具体的工作是交给各个 authentication provider来做的:

\"image\"

这里provider manager包含多个具体的providers:

<bean id=\"authenticationManager\"
class=\"org.acegisecurity.providers.ProviderManager\">
<property name=\"providers\">
<list>
<ref bean=\"daoAuthenticationProvider\"/>
<ref bean=\"ldapAuthenticationProvider\"/>
</list>
</property>
</bean>
ProviderManager is given its list of authentication providers through its providers property.

以DaoAuthenticationProvider举例:

<bean id=\"authenticationProvider\"
class=\"org.acegisecurity.providers.dao.DaoAuthenticationProvider\">
<property name=\"userDetailsService\"
ref=\"userDetailsService\"/>
</bean>

它会要求一个UserDetailsService, 跟它相关的是UserDetails接口

UserDetailsService接口是个简单的接口

public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;
}

UserDetails接口如下:

public interface UserDetails extends Serializable {
GrantedAuthority[] getAuthorities();

String getPassword();

String getUsername();

boolean isAccountNonExpired();

boolean isAccountNonLocked();

boolean isCredentialsNonExpired();

boolean isEnabled();
}

解释一下getAuthorities:该方法返回一个GrantedAuthority[]数组对象,GrantedAuthority是用户权限信息对象,这个对象中定义了一个获取用户权限描述信息的getAuthority()方法。

需要注意Authentication对象才是Spring Security使用的进行安全访问控制用户信息安全对象。实际上,Authentication对象有未认证和已认证两种状态,在作为参数传入认证管理器(AuthenticationManager)的authenticate方法时,是一个未认证的对象,它从客户端获取用户的身份信息(如用户名,密码),可以是从一个登录页面,也可以从Cookie中获取,并由系统自动构造成一个Authentication对象。而这里提到的UserDetails代表一个用户安全信息的源(从数据库,LDAP服务器,CA中心返回),Spring Security要做的就是将这个未认证的Authentication对象和UserDetails进行匹配,成功后将UserDetails中的用户权限信息拷贝到Authentication中组成一个完整的Authentication对象,共其它组件共享。

总结Spring Security之 关于授权,保护web和保护方法

* 关于授权

AcessDecisionManager是管授权的。具体授权(authorization)的工作是交给一系列Voter来做的。每个Voter都实现AccessDecisionVoter接口的vote方法,返回
int ACCESS_GRANTED = 1;(投赞成票)

int ACCESS_ABSTAIN = 0;(投弃权票)

int ACCESS_DENIED = -1; (投反对票)

AccessDecisioinManager有三种实现:

AffirmativeBased -当至少有一个投票者投允许访问票时允许访问

ConsensusBased - 当所有投票者都投允许访问票时允许访问

UnanimousBased - 当没有投票者投拒绝访问票时允许访问

Spring Security提供了一个实用的voter:

RoleVoter participates in a vote when the secured resource has a configuration attribute whose name starts with ROLE_.

* 关于保护web

Spring Security提供一套filter chain保护web应用

注意FilterToBeanProxy

<filter>
<filter-name>Spring Security Filter Chain Proxy</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>

跑下题,说FilterToBeanProxy的作用:filter配置在web.xml里,它是不可能有IOC的概念的,服务没办法自动注射到filter中,这时候有一个办法就是使用WebApplicationContextUtils(如WebApplicationContextUtils.getWebApplicationContext(servletContext).getBean(\"securityManager\"))。按照SpringSide的说法,WebApplicationContextUtils适合厨房,卫生间,草坪,屋顶等非常规场所,汗…这么做的一个缺点是,Spring的API还是入侵到你的code里了(向来对Rod Johnson的入侵论不感冒,感觉这纯是顺手拽过来揍EJB的板砖,不值得深究,pojo粉丝估计要拍我板砖了,俺穿个软猬甲先。入侵论深入人心之后,大家反而愿意对Spring的偶尔入侵指指点点。另外不喜欢Spring的两个方面是,从DDD的角度看Spring不natural;contract first我觉得是扯淡的,或许在之后的博客乱喷一下我的看法)解决入侵的方法就是FilterToBeanProxy, 它把真正的工作代理给target class,而spring拿到target class的类名后,就归它管了。 proxy是个简单的模式,但用在这里感觉还是挺巧妙的。

回到正题,filter chain里至少包括四个filter:

Integration Filter - 拿之前的authentication, 通常是从session里拿。

AuthenticationProcessing Filter - 处理authentication request, 比如登录的时候

Exception Translation Filter - 典型的处理是,把AuthenticationException转登录页,把AccessNeniedException转403错误页

Filter Security Interceptor - 它是真正做权限处理的,把AuthenticaionManager 和AccessDecisionManager串起来.所以FilterSecurityInterceptor是重点。


Tags:
分享至:
最新图文资讯
1 2 3 4 5 6
验证码:点击我更换图片 理智评论文明上网,拒绝恶意谩骂 用户名:
关于我们 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 发展历史