InfoQ

文章

用Acegi Security来保护Grails应用

作者 Fadi Shami译者 宋玮 发布于 2008年3月14日 上午3时49分

社区
Java
主题
安全
标签
Groovy,
Grails

目录

简介
建立RaceTrack例子应用
安装Grails Acegi plugin
创建Acegi Security组件
配制Acegi Security来保护应用
测试

简介

本文论述了grails-acegi plugin与一个简单Grails应用的集成。集成使用了三个主要组件——Groovy, GrailsAcegi Security.

相关厂商内容

缓存系统MemCached的Java客户端优化历程

构建的可伸缩性和达到的性能

免费迷你书下载:深入浅出Struts 2

SOY Framework:Java富客户端快速开发框架

IDC:《软件商成长路线图》白皮书免费下载

相关赞助商

InfoQ中文站Java社区,关注企业Java社区的变化与创新,通过新闻、文章、视频访谈和演讲以及迷你书等为中国Java技术社区提供一流资讯。

Groovy是一个针对Java平台的强大的高级语言,其代码最终被编译为Java字节码。在概念上,它类似于Ruby或Python,可是它与Java平台紧密地集成在一起。这就使你既可利用强大简明的编码语法,又可继续停留在JVM上,从而保护你在已有Java平台和相关类库上的投资。

Grails是一个用Groovy实现的全功能框架。Grails试图通过其核心技术及相关plug-in来解决Web开发中的许多难题。开箱即用的功能包括:

  • 建立在Hibernate之上的对象/关系映射(ORM)层
  • 被称为Groovy Server Pages(GSP)的富于表现的视图(View)技术
  • 构建在Spring MVC之上的控制器(controller)层
  • 构建在Gant(基于Groovy的Ant)之上的一个命令行脚本环境
  • 一个内嵌Jetty容器,被配制为可实时进行资源重载
  • 通过内置Spring容器支持依赖注入(dependency injection)
  • 支持国际化(i18n),这一功能是使用Spring的MessageSource API来构建的
  • 事务服务层,其利用了Spring的事务管理功能
  • 广泛应用了领域特定语言(Domain-Specific Languages——DSLs)

Acegi Security是为企业级软件提供的一个强大的、灵活的安全解决方案,尤其是那些使用了Spring的应用。Acegi提供了全面的认证、授权、基于实例的访问控制、信道安全以及人类用户检测能力。

本文假定你已经阅读过了Grails指南——由Jason Rudolph所编写的Grails入门指南,而且已经实现了其中示例的RaceTrack应用。Grails-acegi plugin将被集成进RaceTrack,为你的应用提供安全性。利用grails-acegi plugin为你免除了在应用中实现Grails拦截器所需的开支,提供了比拦截器更加灵活的解决方案,也节约了你利用Acegi重新实现自己的安全系统所要花费的时间。

建立RaceTrack例子应用

首先,你需要下载Grails 1.0grails-acegi-0.2 plugin以及Java SE JDK 5.0或更新版。

这里,我们假定你已经实现了Grails入门指南中所描述的RaceTrack应用的大部分功能。但是,为了测试grails-acegi plugin,你不必完成整个指南。测试grails-acegi plugin所需的全部东西包括:领域类(domain classes)和controller,controller的脚手架对于测试来说已经足够了。

图 1 —— 创建完racetrack应用后的目录结构

图 1 —— 创建racetrack应用后的目录结构

你的RaceTrack应用目录看起来应该和图1显示的类似。现在,打开\grails-app\domain目录:

图 2 —— 领域类目录

图 2 —— 领域类目录

正如你从图2中看到的,“domain”目录只包含了两个domain类:Race和Registration。现在,打开\grails-app\controllers目录,确认一下每个domain类都有一个对应的controller,如图3所示:

图 3 —— Controllers目录

图 3 —— Controllers目录

这些controller可以是空的、脚手架(scaffold)controller,例如:

  class RaceController { def scaffold = Race }

class RegistrationController { def scaffold = Registration }

这足以让程序跑起来了。在你开始运行RaceTrack应用之后,你将能够在如图4所示的contoller list中看到两个你所创建的controller:

图 4 —— Grails-Acegi Plugin之前的首页

图 4 —— 使用Grails-Acegi Plugin之前的首页

安装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目录

图 5 —— 安装plugin之后所创建的plugins目录

创建Acegi Security组件

下一步是创建代表用户帐号(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中使用)

图 6 —— AuthUser.groovy、Role.groovy和Requestmap.groovy(在AcegiConfig中使用)

图 7 —— 已创建的AcegiConfig.groovy

图 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被创建的时候创建的)

图 8 —— CRUD controllers (Login和Logout controller是在AuthUser和Role被创建的时候创建的)

图 9 —— 安装grails-acegi-plugin之后可用的Controller

图 9 —— 安装grails-acegi-plugin之后可用的Controller

访问RaceTrack首页——它看上去类似于图9所示内容。

配制Acegi Security来保护应用

我们现在创建一个用户角色和管理者角色——首先点击RoleController,输入角色名“user”以及角色描述(图10)。注意RoleController将会把“user”转换成“ROLE_USER”,数据库中和Acegi的配置中将使用“ROLE_USER”。重复同样的步骤创建一个管理者角色。

图 10 —— 创建一个用户角色

图 10 —— 创建一个用户角色

回到首页,点击UserController。现在创建一个拥有“user”角色的用户和另一个拥有“manager”角色的用户,如图11所示:

图 11 —— 创建一个标准用户,激活该帐户并为其指派“user”角色

图 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访问规则

图 12 —— Manager访问规则

注意,一个好的习惯是给manager角色也授予所有用户权限。下一步将给用户角色创建访问规则——在URL域输入“/race/list/**”,在Role域输入“user, manager”(图13——注意角色之间是用逗号分隔的)。这一步骤将创建这样一个访问规则——允许user和manager角色都能访问race列表页面。注意这两个角色你都需要指定——如果你只将该URL指派给user角色,它将覆盖前面给manager指派的规则,这样只有user角色才能访问该页面。为前面定义的其他规则重复这一步骤——这将为race和registration页创建所有的访问规则。

图 13 —— 为/race/list/**页面创建规则——准许user和manager角色访问

图 13 —— 为/race/list/**页面创建规则——准许user和manager角色访问

测试

在RaceTrack首页上点击RaceController或RegistrationController(我们已经保护了这些controller)。你将注意到页面自动重定向到了Login页面。如果你先以manager角色的用户登录,你就能够浏览、创建、更新和删除race和registration页面的任何东西。

图 14 —— 以一个用户身份登录

图 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视图

图 15 —— Race List视图

Figure 16 —— 访问禁止错误页

Figure 16 —— 访问禁止错误页

恭喜你——现在你已经有了RaceTrack应用的一个完整的安全实例了!

查看英文原文:Securing a Grails Application with Acegi Security

5 条回复

回复

简直就是在堆积木嘛! 发表人 tipfoo .oO 发表于 2008年3月18日 上午2时40分
请问如果想增加一个权限,该权限除删除外其他和manager权限一样时如何处理 发表人 Andy Lau 发表于 2008年3月31日 上午7时2分
有个大问题 发表人 建涛 吴 发表于 2008年7月3日 上午2时5分
非常感谢 发表人 li shen 发表于 2008年8月25日 下午11时46分
manager要每个限制里, 不爽. 发表人 chen linbin 发表于 2008年8月30日 下午11时21分
  1. 返回顶部

    简直就是在堆积木嘛!

    2008年3月18日 上午2时40分 发表人 tipfoo .oO

    这样实现权限控制真是太爽了,简直就是在堆积木嘛!

  2. 请问如果想增加一个权限,该权限除删除外其他和manager权限一样时如何处理?

  3. 返回顶部

    有个大问题

    2008年7月3日 上午2时5分 发表人 建涛 吴

    run-app挺正常,一单做成war,发布到tomcat,acegi就彻底完蛋了。所有页面都可以访问,登陆,注册,全都报错。不知道是我配置的问题还是bug~bd,gg搜了一大圈儿也没解决成,郁闷ing

  4. 返回顶部

    非常感谢

    2008年8月25日 下午11时46分 发表人 li shen

    利用您讲的acegi配置,我很快的搭建起了一个基于grails对全县管理系统,并通过测试和部署。非常顺利。支持一下!

  5. 返回顶部

    manager要每个限制里, 不爽.

    2008年8月30日 下午11时21分 发表人 chen linbin

    /race/* 是manager /race/list/* 是user /race/list/* 还要定义user,manager 觉得什么不方便

独家内容

运用Ruby纤程进行异步I/O:NeverBlock和Revactor

Ruby 1.9的纤程(Fibers)和非阻塞I/O越来越收到关注了。我们对来自NeverBlock项目的Mohammad A. Ali和来自Revactor项目的Tone Arcieri进行了访谈。

与杨巍一起探讨OpenSocial

InfoQ中文站有幸与Google中国的产品经理杨巍先生在一起探讨了OpenSocial的相关话题,包括OpenSocial的初衷、构成要素、实现方式、以及要实现它的技术储备等等。

书评:敏捷模式──指向成功的路标

Ryan Cooper对Amr Elssamadisy的新书发表了评价,并认为书中提供了一种为实施敏捷量身定做的框架。本书并没有给出一种人人可用的敏捷方法,而是为读者提供一些模式和工具,用以找出哪些敏捷实践可以最有效地达到该组织机构的特定目标。

构建的可伸缩性和达到的性能:一个虚拟座谈会

这个由业界主要专家们参加的座谈会探究了在使应用程序具备尽可能好的伸缩性及性能的过程中所面临的挑战和思考过程。

OpenSocial的分析与实现

本视频主要对OpenSocial进行了分析,并对实现的方式进行了介绍。其中包括:OpenSocial的开发经验、Container Provider的技术准备、平台的构成要素、具体的规范、以及对未来的展望。

缓存系统MemCached的Java客户端优化历程

Memcached在大型网站被应用得越来越广泛,但是Java客户端并不多,本文作者基于现有的开源客户端进行了封装优化,并翔实记录了这一过程。

超越SOA:动态业务应用的新企业应用框架(2)

在他们文章的第二部分,作者探讨了动态业务应用的架构并介绍了资源容器的概念。他们示范了如何在JEE之上构建这个架构,以及它如何影响实现生产力。

使用ClickOnce细分发布版本

ClickOnce让WinForms应用程序的部署轻而易举。David Cooksey演示了如何在ASP.NET中编写一个HttpHandler来实现对ClickOnce部署的版本细分。