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.

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

简直就是在堆积木嘛! 发表人 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 觉得什么不方便

深度内容

和Google互补的搜索引擎Wolfram|Alpha

Wolfram|Alpha与Google究竟是什么关系,Wolfram|Alpha自己是如何定位的?Wolfram|Alaph在多大程度上是语义网搜索呢?InfoQ中文站就等等这些问题采访了Wolfram研究公司中国区商务经理王翔。

SOA契约成熟度模型

本文说明了所推荐的契约版本管理设计策略是如何与SOA成熟度模型发生联系的。文章目的是为实现版本管理和可组合性提供一个路线图。

数据服务简介

Vijay Narayanan在这篇文章中对数据服务的几个方面进行了介绍,它们都是SOA实践者和数据架构师感兴趣的内容。本文对数据服务的几个方面进行了介绍,包括需求定义,基本原理和好处、范围、开发以及消费模式。

分块云计算

在本文中,Jimmy Nilsson描述了一种他在过去数年间观察到的一种正在缓慢成长的架构风格,他把这种风格称为“分块云计算”。

豆瓣网技术架构变迁

罗马不是一天建成的,豆瓣的技术架构也是随着用户规模的增长一直在持续变化中。在本次演讲中,豆瓣的首席架构师洪强宁将与大家一起分享从上线时的单台服务器架构开始一直到现在的豆瓣架构变迁历程。

融合思想:深入探索S#arp架构

Billy McCafferty展示了S#arp架构,它在ASP.NET MVC框架的基础上,荟萃了当今的最佳实践,应用在ASP.NET Web应用程序的架构设计中。

王雷谈开源以及新兴市场计划

中国作为新兴市场中的新兴市场,是Sun在美国之外实施SSE(SUN Startup Essentials)项目重点关注的地区。在QCon Beijing 2009期间,InfoQ中文站有幸对此项目的负责人王雷先生进行了采访,探讨了关于开源、新兴市场、SSE等话题。

使用HTML5构建下一代的Web Form

HTML5 是由 WHATWG发起的,最开始的名称叫做Web Application 1.0,而后这个标准吸纳了Web Forms 2.0的标准,并一同被W3C组织所采用,合并成为下一代的HTML5标准。