SpringSide 3 中的安全框架

在SpringSide 3的官方文档中,说安全框架使用的是Spring Security 2.0。乍一看,吓了我一跳,以为Acegi这么快就被淘汰了呢。上搜索引擎一搜,发现原来Spring Security 2.0就是Acegi 2.0。悬着的心放下来了。虽然SpringSide 3中关于Acegi的配置文件看起来很不熟悉,但是读了Acegi 2.0的官方文档后,一切都释然了。

先来谈一谈Acegi的基础知识,Acegi的架构比较复杂,但是我希望我下面的只言片语能够把它说清楚。大家都知道,如果要对Web资源进行保护,最好的办法莫过于Filter,要想对方法调用进行保护,最好的办法莫过于AOP。Acegi对Web资源的保护,就是靠Filter实现的。如下图:

一般来说,我们的Filter都是配置在web.xml中,但是Acegi不一样,它在web.xml中配置的只是一个代理,而真正起作用的Filter是作为Bean配置在Spring中的。web.xml中的代理依次调用这些Bean,就实现了对Web资源的保护,同时这些Filter作为Bean被Spring管理,所以实现AOP也很简单,真的是一举两得啊。

Acegi中提供的Filter不少,有十多个,一个一个学起来比较复杂。但是对于我们Web开发者来说,常用的就那么几个,如下图中的被红圈圈标记出来的:

从上到下,它们实现的功能依次是1、制定必须为https连接;2、从Session中提取用户的认证信息;3、退出登录;4、登录;5、记住用户;6、所有的应用必须配置这个Filter。

一般来说,我们写Web应用只需要熟悉这几个Filter就可以了,如果不需要https连接,连第一个也不用熟悉。但是有人肯定会想,这些Filter怎么和我的数据库联系起来呢?不用着急,这些Filter并不直接处理用户的认证,也不直接处理用户的授权,而是把它们交给了认证管理器和决策管理器。如下图:

对于这两种管理器,那也是不需要我们写代码的,Acegi也提供了现成的类。那么大家又奇怪了:又是现成的,那怎么和我的数据库关联起来呢?别着急,其实这两个管理器自己也不做事,认证管理器把任务交给了Provider,而决策管理器则把任务交给了Voter,如下图:

现在我要告诉你们,这里的Provider和Voter也是不需要我们写代码的。不要崩溃,快到目标了。Acegi提供了多个Provider的实现类,如果我们想用数据库来储存用户的认证数据,那么我们就选择DaoAuthenticationProvider。对于Voter,我们一般选择RoleVoter就够用了,它会根据我们配置文件中的设置来决定是否允许某一个用户访问制定的Web资源。

而DaoAuthenticationProvider也是不直接操作数据库的,它把任务委托给了UserDetailService,如下图:

而我们要做的,就是实现这个UserDetailService。图画得不好,大家不要见笑,但是说了这么多总算是引出了我们开发中的关键,那就是我们要实现自己的UserDetailService,它就是连接我们的数据库和Acegi的桥梁。UserDetailService的要求也很简单,只需要一个返回org.springframework.security.userdetails.User对象的loadUserByUsername(String userName)方法。因此,怎么设计数据库都可以,不管我们是用一个表还是两个表还是三个表,也不管我们是用户-授权,还是用户-角色-授权,还是用户-用户组-角色-授权,这些具体的东西Acegi统统不关心,它只关心返回的那个User对象,至于怎么从数据库中读取数据,那就是我们自己的事了。

反过来再看看上面的过程,我们发现,即使我们要做的只是实现自己的UserDetailService类,但是我们不得不在Spring中配置那一大堆的Bean,包括几个Filter,几个Manager,几个Provider和Voter,而这些配置往往都是重复的无谓的。好在Acegi 2.0也认识到了这个问题,所以,它设计了一个<http>标签,让Acegi的配置得到了简化。下面是SpringSide 3中的配置的截图,大家可以看看:

下图是官方文章中的传统Filter设置和<http>元素之间的对应关系:

下面的代码是SpringSide 3中实现UserDetailService的范例,在SpringSide 3的范例中,白衣使用了三个表User、Role、Authority。但是Acegi不关心你用了几个表,它只关心UserDetails对象。而决定用户能否访问指定Web资源的,是RoleVoter类,无需任何修改它可以工作得很好,唯一的缺点是它只认ROLE_前缀,所以搞得白衣的Authority看起来都象角色,不伦不类。

package
 personal.youxia.service.security;

import
 java.util.ArrayList;

import
 java.util.List;

import
 org.springframework.beans.factory.annotation.Required;

import
 org.springframework.dao.DataAccessException;

import
 org.springframework.security.GrantedAuthority;

import
 org.springframework.security.GrantedAuthorityImpl;

import
 org.springframework.security.userdetails.UserDetails;

import
 org.springframework.security.userdetails.UserDetailsService;

import
 org.springframework.security.userdetails.UsernameNotFoundException;

import
 personal.youxia.entity.user.Authority;

import
 personal.youxia.entity.user.Role;

import
 personal.youxia.entity.user.User;

import
 personal.youxia.service.user.UserManager;

/**

* 实现SpringSecurity的UserDetailsService接口,获取用户Detail信息.
 * 
 * 
@author
 calvin
 
*/

public
 
class
 UserDetailServiceImpl 
implements
 UserDetailsService {

private
 UserManager userManager;

public
 UserDetails loadUserByUsername(String userName) 
throws
 UsernameNotFoundException, DataAccessException {
        User user 
=
 userManager.getUserByLoginName(userName);
        
if
 (user 
==
 
null
)
            
throw
 
new
 UsernameNotFoundException(userName 
+
 
"
 不存在
"
);

List
<
GrantedAuthority
>
 authsList 
=
 
new
 ArrayList
<
GrantedAuthority
>
();

for
 (Role role : user.getRoles()) {
            
for
 (Authority authority : role.getAuths()) {
                authsList.add(
new
 GrantedAuthorityImpl(authority.getName()));
            }
        }

//
 目前在MultiDatabaseExample的User类中没有enabled, accountNonExpired,credentialsNonExpired, accountNonLocked等属性
        
//
 暂时全部设为true,在需要时才添加这些属性.

org.springframework.security.userdetails.User userdetail 
=
 
new
 org.springframework.security.userdetails.User(
                user.getLoginName(), user.getPassword(), 
true

true

true

true
, authsList
                        .toArray(
new
 GrantedAuthority[authsList.size()]));

return
 userdetail;
    }

@Required
    
public
 
void
 setUserManager(UserManager userManager) {
        
this
.userManager 
=
 userManager;
    }
}

最后再来说说这个命名的问题,我对Authentication和Authority这两个单词比较反感,两个原因,一是因为它们太生僻了,二是因为它们长得太像了,明明一个是认证,一个是授权,意思相差很远,外貌却如此相似,确实很烦人。如果让我来选择,我喜欢Privilege这个单词,在我刚使用MySQL的时候就跟它很熟了,所以在我的项目中,我可能会用Privilege来代替Authority。如果我们只使用User-Role两级关系,使用RoleVoter默认的ROLE_前缀当然没有关系,如果是像白衣这样是用三层关系,最好还是把这个前缀改一改,以免混淆。
原文地址:http://www.blogjava.net/youxia/archive/2008/12/07/244883.html

原文地址:https://www.cnblogs.com/jpfss/p/11022476.html

时间: 2024-10-15 03:13:50

SpringSide 3 中的安全框架的相关文章

在ns2.35中添加myevalvid框架

在用ns2进行网络视频通信仿真的时候,先要为我们自己的ns2添加evalvid或者myevalvid框架.其中myevalvid框架是由柯志亨老师整合evalvid和ns2之后得出的新框架,笔者建议大家安装该框架,而不要安装原生的evalvid框架.这样就可以结合柯志亨老师的<ns2仿真实验-----多媒体和无线网络通信>这本书,做配套的实验,比较方便. 网上关于myevalvid框架的安装文章很多,大家可以参考去做,笔者会在本文最后给出相关的链接.本文主要是对myevalvid框架源码中的错

java中的集合框架

由于数组具有属性单一,长度不可改变的缺点,于是在程序中我们使用集合来代替它. 集合中不可放入基本数据类型,基本数据类型都是通过自动拆包和自动装箱功能才能放入和取出集合. 分类:Collection接口和Map接口 Collection:存放单一值元素,又可分为list接口类型和set接口类型 list接口类型:存放元素是有序的可重复的,可通过循环来取出其中的元素,实现类ArrayList() set接口类型:hash值排列,存放元素是无序不可重复的,通过指针取出其中元素,实现类HashSet()

step4---&gt;往工程中添加Spring框架----&gt;修改maven的配置文件pom.xml,向工程中添加spring框架的某些模块

1.本文内容: 本文介绍使用maven向自己的项目中添加各种框架的方法,即如何配置maven的pom.xml来让maven帮助管理这些框架(包括Spring.SpringMVC.hibernate框架等等). 2.使用maven向自己的工程中添加框架: 2.1概述 若想使用maven向自己的工程中添加三方框架(如Spring.SpringMVC等),需要先确保你的工程是maven工程,如果你还不知道该如何在myeclipse中建立一个maven web project,请参考相关教程. 2.2使

FreeBSD中的SYSINIT框架【转】

SYSINIT是一个通用的调用排序与分别执行机制的框架.FreeBSD目前使用它来进行内核的动态初始化.SYSINIT使得FreeBSD的内核各子系统可以在内核或模块动态加载链接时被重整.添加.删除.替换,这样,内核和模块加载时就不必去修改一个静态的有序初始化安排表甚至重新编译内核.这个体系也使得内核模块(现在称为KLD可以与内核不同时编译.链接.在引导系统时加载,甚至在系统运行时加载.这些操作是通过"内核链接器"(kernel linker)和"链接器集合"(li

关于jsp商城开发中一些常用框架的介绍

Struts跟Tomcat.Turbine等诸多Apache项目一样,是开源软件,这是它的一大优点,使java商城产品以及jsp商城开发者能更深入的了解其内部实现机制.除此之外,在 java商城开发 中Struts的优点主要集中体现在两个方面:Taglib和页面导航.Taglib是Struts的标记库,比较灵活,能大大提高开发效率.另外,就目前国内的JSP开发者而言,除了使用JSP自带的常用标记外,很少开发自己的标记,或许Struts是一个很好的起点.struts历经6年多的发展,是目前用户数最

简单的介绍下WPF中的MVVM框架

最近在研究学习Swift,苹果希望它迅速取代复杂的Objective-C开发,引发了一大堆热潮去学它,放眼望去各个培训机构都已打着Swift开发0基础快速上手的招牌了.不过我觉得,等同于无C++基础上手学习C#一样,即使将来OC被淘汰,那也是N年之后的事情,如果真的要做IOS开发,趁现在Swift才刚开始,花那么几个月去了解一下OC绝对是一件有帮助的事情. 扯远了,我前几天刚接触到一个叫做mvvm的框架,发现很有意思,带着学习的态度来写点东西,不足之处一起研究.还有一个很重要的原因,我发现不少同

Java项目在jsp页面中引入jquery框架的步骤

环境:在Java  web项目中引入juqery框架 工具:MyEclipse8.5 [步骤如下] A:新建一个Java web项目TestJquery,在WebRoot目录下创建一个jquery文件夹 B:下载jquery-1.8.3.min.js放入jquery文件夹中 C:创建jsp页面 <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%&g

3 weekend110的hadoop中的RPC框架实现机制 + hadoop中的RPC应用实例demo

hadoop中的RPC框架实现机制 RPC是Remotr Process Call, 进程间的远程过程调用,不是在一个jvm里. 即,Controller拿不到Service的实例对象. hadoop中的RPC应用实例demo 在windows是调用端,在linux里是服务端. 在这里,需要LoginServiceinterface.java 停止 出错误了,很明显. 这是个很好的思考题?

菜鸟日记之 java中的集合框架

java中的集合框架图 如图所示:java中的集合分为两种Collection和Map两种接口 可分为Collection是单列集合和Map的双列集合 Collection单列集合:继承了Iterator接口所以具有了iterator()方法 ,该方法返回一个Iterator<T>,这个接口具有 HasNext (),next(),remove()3个方法可以在实现类里完成实现. hasNext():判断是否有下一个元素 cusor是当前的操作下标 next():读取下一个元素 remove(