修改spring security源码实现动态授权

本文介绍如何通过修改Spring Security源代码实现动态授权。具体方法包括调整FilterSecurityInterceptor类中的obtainObjectDefinitionSource方法,以从数据库读取资源和角色信息,并将其转换为Spring Security所需的格式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[code]spring security 安全框架都是通过xml配置文件在容器启动时把资源和角色之间的许可信息加载到内存中,可往往我们需要通过在数据库中配置资源和角色的许可管理来实现动态授权,下面介绍一些通过修改springsecurity源代码的方法来实现动态授权。



首先下载spring security的源代码找到org.springframework.security.intercept.web.FilterSecurityInterceptor类,找到obtainObjectDefinitionSource方法,我们就是要通过修改该方法实现动态授权





private static FilterInvocationDefinitionSource s = null;

private ScRoleResDAO scRoleResDAO;

private ScResourceDAO scResourceDAO;



public ObjectDefinitionSource obtainObjectDefinitionSource() {



if (s == null){

UrlMatcher urlMatcher = new AntUrlPathMatcher(true);

LinkedHashMap requestMap = new LinkedHashMap();



// ApplicationContext context = new ClassPathXmlApplicationContext(

// "spring/dataAccess.xml"

// );

// ScRoleResDAO scRoleResDAO = (ScRoleResDAO)context.getBean("ScRoleResDAO");

// ScResourceDAO scResourceDAO = (ScResourceDAO)context.getBean("ScResourceDAO");



/* 一下这段代码可以忽视,因为每个人的实现方式都不同,

* 这段代码主要是从数据库中取得资源和角色信息的,

* 大家取出来的信息格式可能多种多样,关键是要把这些信息整理成统一的格式

* 参照下面第二段标注为关键代码的部分*/

Map<ScResource, List<ScRoleRes>> map = new TreeMap<ScResource, List<ScRoleRes>>();

ScResourceExample e = new ScResourceExample();

e.setOrderByClause("ORDER_NUM");

List<ScResource> resList = scResourceDAO.selectByExample(e);



ScRoleResExample example = null;

String url = "";

List<ScRoleRes> list = null;

for (ScResource resource : resList) {

url = resource.getUrl();

example = new ScRoleResExample();

example.createCriteria().andUrlEqualTo(url);

list = scRoleResDAO.selectByExample(example);

if (list != null){

map.put(resource, list);

}

}





/**************** 以下是关键代码 *********************/



/*

* 这段代码的重点是生成 requestMap

* requestMap 的 key 的类型为 RequestKey ,需要包含资源的url

* requestMap 的 value 的类型为 ConfigAttributeDefinition ,它需要包含该资源可访问的角色列表信息

* 最后生成 DefaultFilterInvocationDefinitionSource 返回就可以了,

* 当然需要把这个结果保存在内存中,要不然画面上每次刷新都要从数据库中取得信息,资源消耗太大了

* 提供一个刷内存的方法,当数据库中的权限信息改变时要刷新内存中的旧的信息*/

Iterator iterator = map.entrySet().iterator();

ScResource key = null;

List<ScRoleRes> list1 = null;

List<ConfigAttribute> roles = null;

while (iterator.hasNext()) {

Map.Entry entry = (Map.Entry) iterator.next();

key = (ScResource)entry.getKey();

RequestKey reqKey = new RequestKey(key.getUrl());

list1 = (List<ScRoleRes>)entry.getValue();

roles = new ArrayList<ConfigAttribute>();

for (ScRoleRes res : list1) {

roles.add(new SecurityConfig(res.getRole()));

}

requestMap.put(reqKey, new ConfigAttributeDefinition(roles));

}

s = new DefaultFilterInvocationDefinitionSource(urlMatcher,requestMap);

/**************** 以上是关键代码 *********************/

}

return s;

}



/**

* 提供一个刷新内存的静态方法

*/

public static void refresh() {

s = null;





修改启动加载的xml文件,如果此文件是通过命名空间配置的,需要加入



<beans:bean id="_filterSecurityInterceptor"

class="org.springframework.security.intercept.web.FilterSecurityInterceptor"

p:authenticationManager-ref="_authenticationManager"

p:accessDecisionManager-ref="accessDecisionManager">

<beans:property name="objectDefinitionSource">

<beans:value><![CDATA[

CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON

PATTERN_TYPE_APACHE_ANT

/**=ROLE_SUPERVISOR

]]></beans:value>

</beans:property>

<beans:property name="scRoleResDAO" ref="ScRoleResDAO"/>

<beans:property name="scResourceDAO" ref="ScResourceDAO"/>

</beans:bean>



其中objectDefinitionSource并没有实际意义,因为我们已经修改了源代码,如果不想注入这个,把FilterSecurityInterceptor类中的objectDefinitionSource变量去掉应该就可以了,不过没有试过

另外两个DAO是我根据我的代码注入的,大家换成自己的DAO就可以了。





可能说的不清楚,不明白的给我邮件cyoubunketu@126.com[/code]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值