`
chiron.k
  • 浏览: 4858 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

用简单Annotation为Spring Bean增加权限认证

阅读更多
最近在做dwr+Spring的一个应用,直接把Spring的Bean暴露给dwr生成前端的STUB。这样的话,为dwr调用做权限认证,基本上要么用Filter,要么用切面。
用Filter有一个问题是,很多时候,我们并不需为每个调用增加权限认证,但这些请求,也会被拦截,所以不推荐Filter,就像不能因一个坏人而惩罚所有的好人。退一步说,我们可以用现成的Acegi,但配置文件也太麻烦了。而且,我对Acegi有很深的阴影,印象里唯一一个源文件使用四五十个字符变量名的开源项目。
Spring支持AspectJ风格的Annotation,但空方法的POINTCUT和个人感觉很复杂的匹配规则,都不太方便使用。

其实做一个基于Spring BEAN的动态代理,加上权限认证的切面很简单,问题是怎样把这个BEAN再放回到Spring 的容器里,因为BeanFactory更新Singleton Bean的方法是protected修饰的,上次写的方法就是扩展了BeanFactory,但扩展BeanFactory会引发另一个问题,无法把BeanFactory再放回到ServletContext中,因为Spring对WEB 的支持使用的是ApplicationContext的子类。如果扩展ApplicationContext同时,再对BeanFactory做一个Proxy也可以解决问题。但这样写,就太ugly了。
索性彻底一点好了。
最近真的喜欢上用TC来驱动了,测试用的case,

/**
 * @author Chiron K
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"applicationContext.xml"})
public class AuthTest {
	@Autowired
	OtherService otherService = null;

	@Test
	public void testAuthFailed(){
		FakeSession.login("user");
		try{
			otherService.sayHello();
			fail();
		}catch(Exception e){
			if(e instanceof AuthException){
				assertTrue(true);
				System.out.println(e.getMessage());
			}
		}

	}
	
	@Test
	public void testAuthSuccess(){
		FakeSession.login("admin");
		try{
			otherService.sayHello();
			assertTrue(true);
		}catch(Exception e){
			if(e instanceof AuthException){
				fail();
				System.out.println(e.getMessage());
			}
		}

	}
}

这里我们要进行权限测试的类是OtherService,这个类的sayHello方法要求用户必须拥有admin角色。第一个Case,我们登陆用户角色为user,不可以调用sayHello方法。第个Case登陆用户为admin,可以成功调用。
OtherService的接口.
@Secure
public interface OtherService{
	@Auth("admin")
	String sayHello();
}


在这里我们定义了两个Annotation, @Secure标记是否需要为Bean做权限认证,@Auth更小粒度的标记方法和需要的角色。
OtherService的实现
@Component("OtherService")
public class OtherServiceImpl implements OtherService{
	public String sayHello() {
		System.out.println("hello world");
		return "Hello world";
	}
}

这里还要对applicationContext.xml做一些修改,
<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xmlns:context="http://www.springframework.org/schema/context"  
xmlns:aop="http://www.springframework.org/schema/aop"  
xmlns:auth="http://www.iyue.info/schema/auth"
xsi:schemaLocation="http://www.springframework.org/schema/beans   
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
	http://www.springframework.org/schema/aop   
	http://www.springframework.org/schema/aop/spring-aop-2.5.xsd   
	http://www.springframework.org/schema/context   
	http://www.springframework.org/schema/context/spring-context-2.5.xsd
	http://www.iyue.info/schema/auth http://www.iyue.info/schema/auth.xsd">

	<auth:authenticator class="info.iyue.auth.aop.sample.SimpleAuthenticator"/>
	<context:annotation-config/>  
	<context:component-scan base-package="info.iyue.auth.aop.simple"/>  
</beans>

新加了一个命名空间的处理,指定一个Authenticator,这里只做了一个简单的实现,
/**
 * @author Chiron K
 */
public class SimpleAuthenticator implements Authenticator{
	public void authenticate(String role) {
		if(!FakeSession.getRole().equals(role)){
			throw new AuthException("User don't have enough privilege");
		}
	}
}

FakeSession是对HttpSession的简单Mock,
public class FakeSession {
	public static FakeSession session = new FakeSession();
	private String role = null;
	public static void login(String role){
		session.role = role;
	}
	public static String getRole(){
		return session.role;
	}
	public void clear(){
		session.role = null;
	}
}


运行TestCase, 输出:
User don't have enough privilege
hello world

所以对于应用程序来说,只需要:
1 为需要的Spring 容器中的BEAN增加@Secure标记和为需要做权限认证的方法加@Auth标记和角色。
2 在applicationContext.xml中添加对authenticator的定义。
3 实现上一步中指定的authenticator,要求实现Authenticator接口。

很干净吧
这个实现其实主要也是参照了Spring AOP的实现。
通过NamespaceParser,读取到Authenticator的值,并把
自定义BeanFactoryPostProcessor和BeanPostProcessor注册到容器中。
BeanFactoryPostProcessor先于BeanPostProcessor触发,遍历标记有@Secure 的Bean, 当调用BeanPostProcessor.postProcessAfterInitialization时,为具有标记的Bean生成具有Authenticator切面的代理,Spring会更新容器。

具体的实现参附件。测试在sample下面, 依赖包spring2.5.3,spring-test,junit4.4

分享到:
评论
9 楼 daquan198163 2009-04-02  
角色写死在代码里,似乎不妥吧?
建议你采用spring security,比以前的acegi简化了许多
8 楼 chiron.k 2009-04-02  
gty509 写道

其实,自己写一个Aspect,切入到你要验证权限的地方。通过就proceed。失败就跳转或抛出异常就可以了。写aspect比写annotation还简单一些,也容易移植。

其实就是自己写一Aspect,通过就proceed。失败就抛出异常.只是基于自定义的Annotation,而没有使用Spring提供AspectJ的Annotation,因为Aspect切面的定义比较繁琐.至于移植性的话,就要看annotation和xml配置的取舍了.
7 楼 gty509 2009-04-01  
其实,自己写一个Aspect,切入到你要验证权限的地方。通过就proceed。失败就跳转或抛出异常就可以了。写aspect比写annotation还简单一些,也容易移植。

6 楼 chiron.k 2009-04-01  
fangzhouxing 写道

看不懂,请问@Auth("admin") 是如何起作用的?

@Auth为需要权限认证的方法做了一个标记,在SpringContainer初始化后,
把需要做权限认证的BEAN替换成自己生成的代理,
@Auth的作用就是在生成代理的时侯,决定是不是要加进权限认证的切面,
5 楼 chiron.k 2009-04-01  
fangzhouxing 写道

看不懂,请问@Auth("admin") 是如何起作用的?

@Auth为需要权限认证的方法做了一个标记,在SpringContainer初始化后,
把需要做权限认证的BEAN替换成自己生成的代理,
@Auth的作用就是在生成代理的时侯,决定是不是要加进权限认证的切面,
String role = null;
if((role = methodNames.get(method.getName())) != null){
authenticator.authenticate(role);
}
return method.invoke(proxee, args);
4 楼 aninfeel 2009-04-01  
有的人喜欢在一个action里写n个功能。
3 楼 Joo 2009-03-31  
这个解法跟EJB的权限控制很想像啊,不过对EJB容器的依赖少了
2 楼 metadmin 2009-03-31  
有空去权限管理圈子看看, 也欢迎您将文章发布到改圈子。
http://accessmanager.group.iteye.com/
1 楼 fangzhouxing 2009-03-31  
看不懂,请问@Auth("admin") 是如何起作用的?

相关推荐

    权限管理 struts2 hiberante3.5 spring3.0 annotation

    总结起来,"Struts2+Hibernate3.5+Spring3.0(Annotation)"的组合为Java Web开发提供了一个强大的基础架构,尤其在权限管理方面。通过合理的配置和使用注解,可以实现高效、灵活且易于维护的权限控制系统。这不仅...

    Spring Security 安全权限管理手册.pdf

    - **19.3 使用annotation控制方法权限** - **19.3.1 使用@Secured** - 介绍如何使用`@Secured`注解控制方法权限。 - **19.3.2 使用JSR250** - 分析如何使用JSR250规范中的注解来控制方法权限。 **20. 权限管理...

    struts2 hibernate3 spring2.5 annotation 整合

    它通过Action类处理业务逻辑,使用拦截器(Interceptor)来实现如日志、权限验证等功能,并将结果转发到JSP或其他视图组件。 Hibernate3则是一个对象关系映射(ORM)框架,用于处理数据库操作。它简化了Java应用与...

    spring aop权限小实例

    同时,为了实现灵活的权限策略,可以考虑使用预定义的角色和权限模型,以及基于角色的访问控制(RBAC)。 总结起来,Spring AOP提供了一种优雅的方式来处理权限控制和其他横切关注点,通过切面和通知的组合,可以在...

    Spring-注入依赖,AOP,自动注入Bean

    在Spring框架中,依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-...通过学习这些内容,开发者能够更好地理解和掌握Spring框架的核心特性和使用方式,为构建高效、模块化的Java应用打下坚实基础。

    Spring Boot整合Shiro搭建权限管理系统

    在本文中,我们将探讨如何利用Spring Boot和Apache Shiro构建一个权限管理系统。Spring Boot以其便捷的启动和配置方式,使得快速开发变得简单。而Shiro则是一个轻量级的安全框架,用于实现用户认证和授权。 首先,...

    Spring Boot整合Shiro搭建权限管理系统 (2).pdf

    在本文中,我们将探讨如何将 Spring Boot 和 Shiro 结合起来创建一个简单的权限管理系统。 首先,让我们从创建一个 Spring Boot 项目开始: 1. 创建 Maven 工程: 使用 Maven 作为构建工具是标准做法,因为它提供...

    spring中自定义注解(annotation)与AOP中获取注解

    在Spring框架中,自定义注解(Annotation)和AOP(面向切面编程)的结合使用,极大地增强了代码的可读性和可维护性。本文将深入探讨如何在Spring中创建自定义注解以及如何在AOP中有效地获取并利用这些注解。 首先,...

    Spring Security详细介绍及使用含完整代码(值得珍藏)

    ### Spring Security详细介绍及使用 #### 一、Spring Security概述 Spring Security是一款强大的安全框架,它专为基于Spring的企业级应用提供了声明式安全访问控制。该框架利用Spring框架的核心功能,如IoC...

    Spring MVC框架实例

    - 使用 Spring Security 进行权限控制。 - 集成其他中间件,如 Redis 缓存、Quartz 定时任务等。 总结,Spring MVC 为开发者提供了灵活且强大的 Web 开发框架,通过 XML 配置,我们可以自定义各个组件,实现复杂的...

    Spring Boot整合Shiro搭建权限管理系统.pdf

    在本文中,我们将深入探讨如何使用Spring Boot与Apache Shiro框架构建一个权限管理系统。Spring Boot以其简化Spring应用程序的开发过程而闻名,而Shiro则是一个轻量级的安全框架,提供了认证、授权、会话管理和安全...

    Spring Boot整合Shiro搭建权限管理系统教学提纲.docx

    ### Spring Boot整合Shiro搭建权限管理系统知识点解析 #### 一、Spring Boot与Shiro简介 - **Spring Boot**: 是一种简化Spring应用开发的框架,它提供了自动配置、依赖管理等功能,使得开发者能够快速构建独立的...

    Struts1.3 + Hibernate3.3 + Spring3.0 Annotation整合

    2. **配置Hibernate3.3**:在hibernate.cfg.xml中配置数据库连接,然后使用注解或者hbm.xml文件为实体类定义映射。还需配置SessionFactory,并在Spring中管理Session。 3. **配置Spring3.0**:在applicationContext...

    Struts2+Spring2.5+Hibernate3+annotation 整合程序

    在"Struts2+Spring2.5+Hibernate3+annotation"的整合中,注解(Annotation)的使用极大地简化了配置工作。例如,`@Controller`、`@Service`、`@Repository` 和 `@Component` 注解用于标记Spring的Bean,`@...

    struts2+spring2+hibernate3 Annotation的整合

    整合这三个框架时,需要在Spring的配置文件中定义Struts2的插件,使Struts2的动作能够利用Spring管理的Bean。同时,还需要配置Hibernate的SessionFactory,并在Spring中管理数据源和事务配置。 5. **Action类和...

    org.springframework.core.jar

    `springframework-license.txt`文件是Spring框架的许可协议,通常包含了Apache License 2.0或其他开源许可条款,它定义了用户使用Spring框架的法律权限和限制,强调了开源软件的开放源码、自由修改和分发的原则。...

    spring源码雷神spring源码雷神

    2. **AOP(Aspect Oriented Programming)面向切面编程**:Spring提供了强大的AOP支持,可以定义切面、通知、连接点等,方便进行日志记录、事务管理、权限控制等横切关注点的处理。 3. **Bean容器**:Spring的Bean...

Global site tag (gtag.js) - Google Analytics