本文论述了grails-acegi plugin与一个简单Grails应用的集成。集成使用了三个主要组件——Groovy, Grails和Acegi Security.
Groovy是一个针对Java平台的强大的高级语言,其代码最终被编译为Java字节码。在概念上,它类似于Ruby或Python,可是它与Java平台紧密地集成在一起。这就使你既可利用强大简明的编码语法,又可继续停留在JVM上,从而保护你在已有Java平台和相关类库上的投资。
Grails是一个用Groovy实现的全功能框架。Grails试图通过其核心技术及相关plug-in来解决Web开发中的许多难题。开箱即用的功能包括:
Acegi Security是为企业级软件提供的一个强大的、灵活的安全解决方案,尤其是那些使用了Spring的应用。Acegi提供了全面的认证、授权、基于实例的访问控制、信道安全以及人类用户检测能力。
本文假定你已经阅读过了Grails指南——由Jason Rudolph所编写的Grails入门指南,而且已经实现了其中示例的RaceTrack应用。Grails-acegi plugin将被集成进RaceTrack,为你的应用提供安全性。利用grails-acegi plugin为你免除了在应用中实现Grails拦截器所需的开支,提供了比拦截器更加灵活的解决方案,也节约了你利用Acegi重新实现自己的安全系统所要花费的时间。
首先,你需要下载Grails 1.0、grails-acegi-0.2 plugin以及Java SE JDK 5.0或更新版。
这里,我们假定你已经实现了Grails入门指南中所描述的RaceTrack应用的大部分功能。但是,为了测试grails-acegi plugin,你不必完成整个指南。测试grails-acegi plugin所需的全部东西包括:领域类(domain classes)和controller,controller的脚手架对于测试来说已经足够了。
图 1 —— 创建racetrack应用后的目录结构
你的RaceTrack应用目录看起来应该和图1显示的类似。现在,打开\grails-app\domain目录:
图 2 —— 领域类目录
正如你从图2中看到的,“domain”目录只包含了两个domain类:Race和Registration。现在,打开\grails-app\controllers目录,确认一下每个domain类都有一个对应的controller,如图3所示:
图 3 —— Controllers目录
这些controller可以是空的、脚手架(scaffold)controller,例如:
class RaceController { def scaffold = Race }
class RegistrationController { def scaffold = Registration }
这足以让程序跑起来了。在你开始运行RaceTrack应用之后,你将能够在如图4所示的contoller list中看到两个你所创建的controller:
图 4 —— 使用Grails-Acegi Plugin之前的首页
下一步是安装grails-acegi plugin,这样RaceTrack就可以利用该plugin所提供的基于角色的安全防护。在命令提示行中,进入到“racetrack”目录并运行如下命令:
grails install-plugin [path-to]/grails-acegi-0.2.zip
这一命令会在“racetrack”目录下创建一个plugins目录,如图5所示:
图 5 —— 安装plugin之后所创建的plugins目录
下一步是创建代表用户帐号(Accounts)和角色(Roles)的领域类。运行如下命令开始这一过程:
grails create-auth-domains AuthUser Role
这一命令将创建两个领域类(AuthUser和Role)、建立AcegiConfig类、并创建Login和Logout两个controller。AuthUser领域类代表你的用户,因此每个新用户都将在Auth_User表中创建一条新的记录。Role领域类代表每个用户所拥有的安全角色,Role将被指派给AuthUser。所有这些类都显示在图6中。
AcegiConfig类(图7)定义了你的应用的安全配置。配置中包括:用户领域类的名字(本例为AuthUser)以及角色领域类的名字(本例为Role),使用动态还是静态安全Urls,怎样设置email警报(打开或关闭它们)。
图 6 —— AuthUser.groovy、Role.groovy和Requestmap.groovy(在AcegiConfig中使用)
图 7 —— 已创建的AcegiConfig.groovy
为了创建新的AuthUser,创建新的Role并指派给AuthUser,我们还得运行两个命令。其一是产生领域类的CRUD控制:
grails generate-manager
第二个是为controller和domain产生registration:
grails generate-registration
这些命令给了用户注册并创建其用户名和口令的能力,默认的安全角色将被指派给该用户。从图8可以看到所产生的这一controller集合:
图 8 —— CRUD controllers (Login和Logout controller是在AuthUser和Role被创建的时候创建的)
图 9 —— 安装grails-acegi-plugin之后可用的Controller
访问RaceTrack首页——它看上去类似于图9所示内容。
我们现在创建一个用户角色和管理者角色——首先点击RoleController,输入角色名“user”以及角色描述(图10)。注意RoleController将会把“user”转换成“ROLE_USER”,数据库中和Acegi的配置中将使用“ROLE_USER”。重复同样的步骤创建一个管理者角色。
图 10 —— 创建一个用户角色
回到首页,点击UserController。现在创建一个拥有“user”角色的用户和另一个拥有“manager”角色的用户,如图11所示:
图 11 —— 创建一个标准用户,激活该帐户并为其指派“user”角色
我们创建的角色和用户现在已经足够用作配置了,下一步是保护RaceTrack应用。有两种方法保护你的URLs:一种是动态,通过RequestmapController来实现;另一种是静态的,直接编辑AcegiConfig.groovy文件。动态配置是被推荐的选项,下面我们继续进行动态配置工作。
在我们保护应用之前,需要考虑一下应用需要给予怎样的访问规则。一个manager被允许读/写访问应用中的任何页面,即:
/race/*
/registration/*
一个用户被允许只读访问某些页面,包括:
/race/list/*
/race/show/*
/registration/list/*
/registration/show/*
这些规则需要使用RequestmapController翻译成Acegi请求映射(Acegi request map)中的条目。从RaceTrack首页上点击RequestmapController,转到“create a new requestmap”页面。在URL域内填写上“/race/**”,在Role域填写为“manager”(图12)——这将创建一条规则,允许任何拥有manager角色的用户访问/race下的所有URLs。同样的方法可以配置好registration(URL:/registration/**)。
图 12 —— Manager访问规则
注意,一个好的习惯是给manager角色也授予所有用户权限。下一步将给用户角色创建访问规则——在URL域输入“/race/list/**”,在Role域输入“user, manager”(图13——注意角色之间是用逗号分隔的)。这一步骤将创建这样一个访问规则——允许user和manager角色都能访问race列表页面。注意这两个角色你都需要指定——如果你只将该URL指派给user角色,它将覆盖前面给manager指派的规则,这样只有user角色才能访问该页面。为前面定义的其他规则重复这一步骤——这将为race和registration页创建所有的访问规则。
图 13 —— 为/race/list/**页面创建规则——准许user和manager角色访问
在RaceTrack首页上点击RaceController或RegistrationController(我们已经保护了这些controller)。你将注意到页面自动重定向到了Login页面。如果你先以manager角色的用户登录,你就能够浏览、创建、更新和删除race和registration页面的任何东西。
图 14 —— 以一个user身份登录
回到RaceTrack首页并点击LogoutController——这将使你的用户session失效并登出。再次点击LoginController,但是这次以user角色的用户登录。如果你转向/race/list的子页面(直接访问http://localhost:8080/racetrack/race/list或通过controller转过去),你将看到race/list视图(图15)。
记得么,访问规则只允许manager创建新记录,user角色只允许从List和Show页面读取数据——这意味着如果你以user角色的用户登录并点击了New Race(http://localhost:8080/racetrack/race/create),Acegi将阻止你浏览该页面,它阻止了一个新记录的创建。
它是怎么工作的呢?回想一下,我们给manager角色授权可以访问/race/*,但是只给user角色授权访问/race/list/*和/race/show/*。当拥有“user”角色的用户试图访问/race/create页面时,Acegi察看该用户所拥有的所有角色,发现其只有“user”角色——因为我们的Request map说了,必须是“manager”角色才被授权访问这一页面,于是访问这一页面的许可被禁止了。
顺便讲一下,在一个真正的应用中,你可能想要显示一个比默认错误页(图16)更好看的错误页。
图 15 —— Race List视图
Figure 16 —— 访问禁止错误页
恭喜你——现在你已经有了RaceTrack应用的一个完整的安全实例了!
查看英文原文:Securing a Grails Application with Acegi Security