`
孙宁振
  • 浏览: 35077 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类

spring security 2.0 的简单配置使用(补)——用aop控制method级权限

阅读更多

上次写了spring security 2.0 的简单配置使用 ,这里再做一下补充。

method级别的权限控制可以通过spring aop来实现。

pointcut:

    <aop:config>
        <aop:pointcut id="securityPointcut"
            expression="execution(** org.catspaw.ss2test1.service.*Service+.*(..))" />
        <aop:advisor advice-ref="accessDeniedInterceptor"
            pointcut-ref="securityPointcut" order="0" />
        <aop:advisor advice-ref="methodSecurityInterceptor"
            pointcut-ref="securityPointcut" order="1" />
    </aop:config>

当调用org.catspaw.ss2test1.service包下所有Service结尾的类的任何方法时,通知accessDeniedInterceptor和methodSecurityInterceptor两个Interceptor。

 

MethodSecurityInterceptor,作用和FilterSecurityInterceptor差不多,如果授权不通过,也会抛异常。

    <bean id="methodSecurityInterceptor"
        class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="accessDecisionManager" ref="accessDecisionManager" />
        <property name="objectDefinitionSource"
            ref="databaseMethodDefinitionSource" />
    </bean>

 DefaultMethodDefinitionSource,作用类似于DefaultFilterInvocationDefinitionSource

    <bean id="databaseMethodDefinitionSource"
        class="org.catspaw.ss2test1.security.DefaultMethodDefinitionSource">
        <constructor-arg index="0">
            <bean
                class="org.catspaw.ss2test1.security.SimpleAspectJMethodMatcher" />
        </constructor-arg>
        <constructor-arg index="1">
            <bean class="org.catspaw.ss2test1.security.MethodMapFactoryBean">
                <property name="resourceDao" ref="resourceDao" />
            </bean>
        </constructor-arg>
    </bean>

 实现:

package org.catspaw.ss2test1.security;

import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

/**
 * 从数据库获取被访问的资源所需要的权限标识符
 * 这里只处理Method(方法)资源
 * 
 * @author 孙宁振
 */
public class DefaultMethodDefinitionSource extends
        AbstractFallbackMethodDefinitionSource {

    private Matcher<String, Method>                          methodMatcher;
    private LinkedHashMap<String, ConfigAttributeDefinition> methodMap = new LinkedHashMap<String, ConfigAttributeDefinition>();

    public DefaultMethodDefinitionSource(Matcher<String, Method> methodMatcher,
            LinkedHashMap<String, ConfigAttributeDefinition> methodMap) {
        this.methodMatcher = methodMatcher;
        this.methodMap = methodMap;
    }

    public Collection getConfigAttributeDefinitions() {
        return Collections.unmodifiableCollection(getMethodMap().values());
    }

    @Override
    protected ConfigAttributeDefinition findAttributes(Method method,
            Class targetClass) {
        Set<Entry<String, ConfigAttributeDefinition>> set = getMethodMap()
                .entrySet();
        for (Entry<String, ConfigAttributeDefinition> entry : set) {
            String pattern = entry.getKey();
            boolean matched = getMethodMatcher().match(pattern, method);
            if (matched) {
                return entry.getValue();
            }
        }
        return null;
    }

    @Override
    protected ConfigAttributeDefinition findAttributes(Class clazz) {
        return null;
    }

    public Map<String, ConfigAttributeDefinition> getMethodMap() {
        return methodMap;
    }

    public Matcher<String, Method> getMethodMatcher() {
        return methodMatcher;
    }
}

 

SimpleAspectJMethodMatcher ,Matcher接口省略

package org.catspaw.ss2test1.security;

import java.lang.reflect.Method;
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.ShadowMatch;

/**
 * Method匹配器实现
 * 用AspectJ PointCut表达式匹配目标方法
 * 
 * @author 孙宁振
 */
public class SimpleAspectJMethodMatcher implements Matcher<String, Method> {

    private PointcutParser pointcutParser = PointcutParser
                                                  .getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution();

    public boolean match(String pattern, Method method) {
        pattern = "execution(" + pattern + ")";
        PointcutExpression pe = pointcutParser.parsePointcutExpression(pattern);
        ShadowMatch match = pe.matchesMethodExecution(method);
        return match.alwaysMatches();
    }

    public void setPointcutParser(PointcutParser pointcutParser) {
        this.pointcutParser = pointcutParser;
    }

    public PointcutParser getPointcutParser() {
        return pointcutParser;
    }
}

 

 MethodMapFactoryBean ,作用类似于RequestMapFactoryBean:

package org.catspaw.ss2test1.security;

import java.util.LinkedHashMap;
import java.util.List;
import org.catspaw.ss2test1.dao.ResourceDao;
import org.catspaw.ss2test1.model.Resource;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.security.ConfigAttributeDefinition;

public class MethodMapFactoryBean implements FactoryBean {

    private static final String                              RESOURCE_TYPE = "METHOD";
    private ResourceDao                                      resourceDao;
    private LinkedHashMap<String, ConfigAttributeDefinition> methodMap;

    public void init() {
        List<Resource> resources = resourceDao.find(RESOURCE_TYPE);
        methodMap = new LinkedHashMap<String, ConfigAttributeDefinition>();
        for (Resource resource : resources) {
            ConfigAttributeDefinition definition = new ConfigAttributeDefinition(
                    resource.getAuthority());
            methodMap.put(resource.getResourceString(), definition);
        }
    }

    public Object getObject() throws Exception {
        if (methodMap == null) {
            init();
        }
        return methodMap;
    }

    public Class getObjectType() {
        return LinkedHashMap.class;
    }

    public boolean isSingleton() {
        return true;
    }

    public ResourceDao getResourceDao() {
        return resourceDao;
    }

    public void setResourceDao(ResourceDao resourceDao) {
        this.resourceDao = resourceDao;
    }
}

 

另外,AccessDeniedInterceptor 的作用是在授权失败,抛出异常后,做一些其他的处理工作,需要实现ThrowsAdvice 接口。比如:

package org.catspaw.ss2test1.security;

import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
import org.springframework.security.AccessDeniedException;

/**
 * 控制权限的AOP拦截器抛出AccessDeniedException后,进行相应后续处理
 * 
 * @author 孙宁振
 *
 */
public class AccessDeniedInterceptor implements ThrowsAdvice {

    public void afterThrowing(Method method, Object[] args, Object target,
            AccessDeniedException exception) {
        System.out.println("access denied.....");
        //TODO 通过DatabaseMethodDefinitionSource拒绝访问后的处理
    }
}

 注意:accessDeniedInterceptor的order需要在methodSecurityInterceptor的order之前,否则methodSecurityInterceptor抛出异常后,accessDeniedInterceptor将不会执行。

 

HelloService

    <bean id="helloService"
        class="org.catspaw.ss2test1.service.impl.HelloServiceImpl">
    </bean>

 接口:

package org.catspaw.ss2test1.service;

public interface HelloService {

    void hello();

    void hello(String name);
}

 

实现:

package org.catspaw.ss2test1.service.impl;

import org.catspaw.ss2test1.service.HelloService;

public class HelloServiceImpl implements HelloService {

    public void hello() {
        System.out.println("hello.......");
    }

    public void hello(String name) {
        System.out.println("hello " + name);
    }
}

 测试用的Servlet

package org.catspaw.ss2test1.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.catspaw.ss2test1.service.HelloService;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class HelloServlet extends HttpServlet {

    private HelloService helloService;

    @Override
    public void init() throws ServletException {
        super.init();
        ApplicationContext ctx = WebApplicationContextUtils
                .getRequiredWebApplicationContext(getServletContext());
        helloService = (HelloService) ctx.getBean("helloService");
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String name = request.getParameter("name");
        if (name != null) {
            helloService.hello(name);
        } else {
            helloService.hello();
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

 

附demo
所用到的jar:spring2.0.7,hibernate3.2.5&jpa,spring-security2.0.3,ehcache1.3

数据库:mysql5,建好相应数据库后,把<prop key="hibernate.hbm2ddl.auto">none</prop>的none改为create即可在运行时自动建表
登录入口为/spring_security_login

用户名   密码
admin    admin
aaa      aaa
bbb      bbb

分享到:
评论
5 楼 wotaikelela 2011-03-17  
不错!不错!
4 楼 striveandlive 2009-11-16  
大牛呀--
3 楼 gdyycn 2009-02-02  
十分感谢分享!谢谢!
2 楼 wei_jing 2008-08-20  
恩。 
这种方法也行,其实,我一直在找spring scurity 的默认配置,然后修改一下。
在配置文件中,使用:
<global-method-security secured-annotations="enabled">
		<protect-pointcut
		expression="execution(* org.springframework.samples.petclinic.Clinic.storeVisit(..))"
		access="ROLE_SUPERVISOR" />
</global-method-security>



因此,只要知道这个工作过程,再修改一下,让expression 和 access 从数据库中读出来就行了。
它是先使用org.springframework.security.intercept.method.ProtectPointcutPostProcessor读取expression 和 access的值,然后后注册到MapBasedMethodDefinitionSource中,MapBasedMethodDefinitionSource其实也是MethodDefinitionSource的一个实现类来的。可惜,我不知道下一步它怎样进行啦。我以为是到此结束。很高兴的启动服务器,一切正常。。用一个没有操作权限的用户去运行,很好,运行也正常。但我确觉得不对路啦,应该抛异常才对。我相信是方法拦截器的问题,我没有配置。。。
1 楼 40020072 2008-08-19  
真的好厉害。非常非常感谢~

相关推荐

    Spring Security 2.0.x完全中文参考文档

    包含了一系列简单的示例,用于演示如何配置和使用Spring Security。 - **3.2. Contacts** 通过这个示例展示如何在实际的应用场景中使用Spring Security。 - **3.3. LDAP例子** 展示了如何使用LDAP作为用户...

    spring security3 中文版本

    - **安全和 AOP 建议**:Spring Security 提供了 AOP 支持,可以用来在运行时动态地决定是否允许执行特定的方法调用。 - **安全对象和 AbstractSecurityInterceptor**:提供了抽象的安全拦截器,可以用于拦截方法...

    spring-security 官方文档 中文版

    - **&lt;global-method-security&gt; 元素**:用于配置全局的方法级安全性策略。 - **使用 protect-pointcut 添加安全切点**:通过声明式的切点来控制方法访问权限。 **2.5 默认的 AccessDecisionManager** - **自定义 ...

    Spring_Security_2.0.x中文参考文档

    ### Spring Security 2.0.x中文参考文档知识点详解 #### 序言与入门 - **Spring Security 是什么?** - Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架。 - **历史** - Spring Security 的...

    Spring Security 中文教程.pdf

    ### Spring Security 中文教程知识点概览 #### 一、Spring Security简介 - **Spring Security**是一种全面...Spring Security提供了极其丰富的特性和灵活性,适用于从简单的Web应用到复杂的企业级系统的安全性需求。

    Java之Spring AOP 实现用户权限验证

    在本文中,我们将重点探讨如何使用Spring AOP实现用户权限验证。 首先,权限验证是任何应用程序中不可或缺的一部分,尤其是涉及到用户登录和访问控制的场景。通过Spring AOP,我们可以将权限验证的逻辑与业务代码...

    AOP控制权限编程例子

    **AOP编程与权限控制详解** 在软件开发中,面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,旨在减少代码的重复性和提高代码的可维护性。AOP允许程序员定义“方面”,这些方面是关注点的模块...

    spring security3.0 spring权限问题

    ### Spring Security 3.0权限问题相关知识点 #### 一、Spring Security简介 **1.1 Spring Security 是什么?** Spring Security 是一个强大的且高度可定制的身份验证和访问控制框架。它为Java应用提供了声明式的...

    springSecurity3简单例子

    在本示例中,我们将探讨如何使用Spring Security 3构建一个简单的登录系统,并通过SQL实现用户身份验证,以及利用AOP(面向切面编程)进行权限配置。 首先,我们需要在项目中引入Spring Security的依赖。Spring ...

    spring security 参考手册中文版

    Spring Security 参考 1 第一部分前言 15 1.入门 16 2.介绍 17 2.1什么是Spring Security? 17 2.2历史 19 2.3版本编号 20 2.4获得Spring安全 21 2.4.1使用Maven 21 Maven仓库 21 Spring框架 22 2.4.2 Gradle 23 ...

    springsecurity的帮助文档

    - **全局方法安全元素**:通过 `&lt;global-method-security&gt;` 元素统一管理方法级安全配置。 - **拦截方法 Bean 装饰器**:提供了一种灵活的方式来管理方法调用前后的安全检查。 - **默认决策管理器**: - **...

    Spring_Security-3.0.1_中文自学教程.pdf

    - **Tutorial 示例**:通过简单的示例介绍如何使用 Spring Security。 - **Contacts**:演示如何使用 Spring Security 保护 Web 应用程序。 - **LDAP 例子**:展示如何集成 LDAP 进行用户认证。 - **CAS 例子**:...

    Spring Security-3中文官方文档

    Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架,用于Java应用程序的安全性。它提供了全面的安全解决方案,包括Web安全、方法级别的访问控制、权限管理等。在Spring Security 3.0.1版本中,主要...

    SpringSecurity 3.0.1.RELEASE.CHM

    5.5. Spring Security中的访问控制(验证) 5.5.1. 安全和AOP建议 5.5.2. 安全对象和AbstractSecurityInterceptor 5.5.2.1. 配置属性是什么? 5.5.2.2. RunAsManager 5.5.2.3. AfterInvocationManager 5.5.2.4...

    Spring Security3技术手册

    - 学习如何在Spring Security的配置文件中定义数据源,并使用JDBC来管理用户和权限。 - **示例代码**: 在`spring-security.xml`中配置`&lt;authentication-manager&gt;`和`&lt;authentication-provider&gt;`。 - **2.2 数据库...

    SPRING SECURITY DOC

    Spring Security的访问控制主要体现在两个层面:URL过滤(Filter Security Interceptors)和方法调用过滤(Method Security Interceptors)。URL过滤主要用于控制HTTP请求的访问权限,而方法调用过滤则可以用于控制...

    spring-security-reference

    Spring Security 在运行时与 Spring 框架紧密集成,利用 Spring 的依赖注入和 AOP 功能来实现安全控制。 ##### 5.2 共享组件 - **SecurityContextHolder 和 SecurityContext 对象**:用于存储当前用户的认证信息。...

    Spring Security 3.0.1 pdf 中文参考文档

    - **内容:** 包含了一个简单的 Spring Security 应用程序示例,用于演示如何配置和使用 Spring Security。 **3.2 Contacts** - **内容:** 介绍如何在 Spring Security 中配置联系人管理功能。 **3.3 LDAP 例子**...

Global site tag (gtag.js) - Google Analytics