<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"
default-lazy-init="true">
<!-- TODO 原来Spring2.5和SpringSecurity2.0.4的文件头
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"
default-autowire="autodetect" default-lazy-init="true">
-->
<description>SpringSecurity安全配置</description>
<!-- http安全配置 -->
<s:http auto-config="true" use-expressions="true">
<!-- 对登录页面不进行拦截,至于后面的*,是因为请求的页面可能包含一些参数! -->
<s:intercept-url pattern="/login.jsp*" filters="none"/>
<!-- TODO
<s:intercept-url pattern="/login" access="hasAnyRole('IS_AUTHENTICATED_ANONYMOUSLY')"/>
<s:intercept-url pattern="/**" access="hasAnyRole('ROLE_数据模块')"/> -->
<s:intercept-url pattern="/style/**" filters="none"/>
<s:intercept-url pattern="/image/**" filters="none"/>
<s:intercept-url pattern="/script/**" filters="none"/>
<s:intercept-url pattern="/fckeditor/**" filters="none"/>
<s:intercept-url pattern="/decorators/**" filters="none"/>
<s:intercept-url pattern="/uploads/**" filters="none"/>
<s:intercept-url pattern="/common/**" filters="none"/>
<!-- TODO 若不配置权限,则以匿名用户访问所有页面!
<s:intercept-url pattern="/activity_publicize/activity-publicize!save*" access="hasAnyRole('ROLE_修改活动宣传')"/>
<s:intercept-url pattern="/activity_publicize/activity-publicize!delete*" access="hasAnyRole('ROLE_修改活动宣传')"/>
<s:intercept-url pattern="/activity_publicize/activity-publicize*" access="hasAnyRole('ROLE_浏览活动宣传')"/> -->
<!-- 配置登录页面!
<s:form-login login-page="/login" default-target-url="/index/main" authentication-failure-url="/index/main"/> -->
<s:form-login login-page="/login" default-target-url="/index.jsp" authentication-failure-url="/login?error=true"/>
<s:logout logout-success-url="/index.jsp"/>
<!-- TODO 在SS3.0.x中,自定义的filter的配置要放在s:http里 -->
<s:custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/>
</s:http>
<!--<s:http auto-config="true" access-decision-manager-ref="accessDecisionManager">
<s:form-login login-page="/logreg.action" default-target-url="/"
authentication-failure-url="/logreg.action?error=true" />
<s:logout logout-success-url="/" />
<s:remember-me key="e37f4b31-0c45-11dd-bd0b-0800200c9a66" />
</s:http>-->
<!-- 认证配置,使用userDetailsService提供的用户信息 -->
<s:authentication-manager alias="authenticationManager">
<s:authentication-provider user-service-ref="userDetailsService">
<!-- TODO 可设置hash使用sha1或md5散列密码后再存入数据库 -->
<s:password-encoder hash="plaintext"></s:password-encoder>
</s:authentication-provider>
</s:authentication-manager>
<!-- 项目实现的用户查询服务 -->
<bean id="userDetailsService" class="com.byd.info_platform.service.account.UserDetailsServiceImpl" />
<!--JCaptcha验证码服务
<bean id="captchaService" class="com.octo.captcha.service.image.DefaultManageableImageCaptchaService">
<property name="captchaEngine">
<bean class="com.zenithen.skynet.skynet.security.jcaptcha.GMailEngine" />
</property>
默认生成的图片180秒过期 , 可另行设置
<property name="minGuarantedStorageDelayInSeconds" value="180" />
</bean> -->
<!-- 重新定义的FilterSecurityInterceptor,使用databaseDefinitionSource提供的url-授权关系定义 --><!-- <bean id="filterSecurityInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor"> SpringSecurity2.0.x中使用 -->
<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<!--<s:custom-filter before="FILTER_SECURITY_INTERCEPTOR" />
<s:custom-filter ref="databaseDefinitionSource" before="FILTER_SECURITY_INTERCEPTOR"/>-->
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource" ref="databaseDefinitionSource" /><!-- <property name="objectDefinitionSource" ref="databaseDefinitionSource" /> 注:objectDefinitionSource在SS3中已经标记为过时了,要换用securityMetadataSource -->
</bean>
<!-- DefinitionSource工厂,使用resourceDetailsService提供的URL-授权关系.
<bean id="databaseDefinitionSource" class="com.zenithen.skynet.security.springsecurity.DefinitionSourceFactoryBean"> -->
<bean id="databaseDefinitionSource" class="com.byd.info_platform.service.account.DefinitionSourceFactoryBean">
<property name="resourceDetailsService" ref="resourceDetailsService" />
</bean>
<!-- 项目实现的URL-授权查询服务 -->
<bean id="resourceDetailsService" class="com.byd.info_platform.service.account.ResourceDetailsServiceImpl" />
<!-- 授权判断配置, 将授权名称的默认前缀由ROLE_改为A_. --><!-- <bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased"> SpringSecurity2.0.x中使用 -->
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list><!-- <bean class="org.springframework.security.vote.RoleVoter"> SpringSecurity2.0.x中使用 -->
<bean class="org.springframework.security.access.vote.RoleVoter">
<property name="rolePrefix" value="A_" />
</bean><!-- <bean class="org.springframework.security.vote.AuthenticatedVoter" /> SpringSecurity2.0.x中使用 -->
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</property>
</bean>
</beans>
DefinitionSourceFactoryBean类和ResourceDetailsServiceImpl类
/**
* Copyright (c) 2005-2009 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*
* $Id: DefinitionSourceFactoryBean.java 619 2009-11-03 16:38:04Z calvinxiu $
*/
package com.byd.info_platform.service.account;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.RequestKey;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;
/**
* DefinitionSource工厂.
*
* 由注入的resourceDetailService读取在数据库或其它地方中定义的URL-授权关系, 提供LinkedHashMap<String,
* String>形式的URL及授权关系定义, 并最终转为SpringSecurity所需的LinkedHashMap<RequestKey,
* Collection<ConfigAttribute>>形式的定义.
*
* @see org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource
* @see ResourceDetailsService
*
* @author calvin
* @author leeoo
*/
public class DefinitionSourceFactoryBean implements FactoryBean {
private ResourceDetailsService resourceDetailsService;
public void setResourceDetailsService(ResourceDetailsService resourceDetailsService) {
this.resourceDetailsService = resourceDetailsService;
}
/**
* 返回注入了AntStyle的URLMatcher和ResourceDetailService提供的RequestMap的DefaultFilterInvocationSecurityMetadataSource.
*/
public Object getObject() throws Exception {
// 3.x之前的版本使用~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LinkedHashMap<RequestKey, ConfigAttributeDefinition> requestMap = buildRequestMap();
// UrlMatcher matcher = getUrlMatcher();
// DefaultFilterInvocationDefinitionSource definitionSource = new DefaultFilterInvocationDefinitionSource(matcher,
// requestMap);
// 3.x之前的版本使用~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LinkedHashMap<RequestKey, Collection<ConfigAttribute>> requestMap = buildRequestMap();
UrlMatcher matcher = getUrlMatcher();
DefaultFilterInvocationSecurityMetadataSource definitionSource = new DefaultFilterInvocationSecurityMetadataSource(matcher,
requestMap);
return definitionSource;
}
/**
* @see FactoryBean#getObjectType()
*/
public Class getObjectType() {
// return FilterInvocationDefinitionSource.class; // 3.x之前的版本使用
return FilterInvocationSecurityMetadataSource.class;
}
/**
* @see FactoryBean#isSingleton()
*/
public boolean isSingleton() {
return true;
}
/**
* 提供Ant Style的URLMatcher.
*/
protected UrlMatcher getUrlMatcher() {
return new AntUrlPathMatcher();
}
/**
* 将resourceDetailService提供LinkedHashMap<String, String>形式的URL及授权关系定义
* 转化为DefaultFilterInvocationSecurityMetadataSource需要的LinkedHashMap<RequestKey,
* Collection<ConfigAttribute>>形式.
*/
// 注:SpringSecurity3里面修改了几个类,其中的ConfigAttributeEditor类已过时,改用SecurityConfig类了;ConfigAttributeDefinition类已废弃
protected LinkedHashMap<RequestKey, Collection<ConfigAttribute>> buildRequestMap() throws Exception {// NOSONAR
LinkedHashMap<String, String> srcMap = resourceDetailsService.getRequestMap();
LinkedHashMap<RequestKey, Collection<ConfigAttribute>> distMap = new LinkedHashMap<RequestKey, Collection<ConfigAttribute>>();
for (Map.Entry<String, String> entry : srcMap.entrySet()) {
RequestKey key = new RequestKey(entry.getKey(), null);
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
atts = SecurityConfig.createListFromCommaDelimitedString(entry.getValue());
distMap.put(key, atts);
}
return distMap;
}
/*
// 3.x之前的版本使用如下写法
protected LinkedHashMap<RequestKey, Collection<ConfigAttribute>> buildRequestMap() throws Exception {
// protected LinkedHashMap<RequestKey, ConfigAttributeDefinition> buildRequestMap() throws Exception { // 3.x之前的版本使用
LinkedHashMap<String, String> srcMap = resourceDetailsService.getRequestMap();
LinkedHashMap<RequestKey, Collection<ConfigAttribute>> distMap = new LinkedHashMap<RequestKey, Collection<ConfigAttribute>>();
// LinkedHashMap<RequestKey, ConfigAttributeDefinition> distMap = new LinkedHashMap<RequestKey, ConfigAttributeDefinition>(); // 3.x之前的版本使用
ConfigAttributeEditor editor = new ConfigAttributeEditor();
for (Map.Entry<String, String> entry : srcMap.entrySet()) {
RequestKey key = new RequestKey(entry.getKey(), null);
if (StringUtils.isNotBlank(entry.getValue())) {
editor.setAsText(entry.getValue());
// distMap.put(key, (ConfigAttributeDefinition) editor.getValue()); // 3.x之前的版本使用
distMap.put(key, (Collection<ConfigAttribute>) editor.getValue());
} else {
// distMap.put(key, ConfigAttributeDefinition.NO_ATTRIBUTES); // 3.x之前的版本使用
// distMap.put(key, ConfigAttribute.NO_ATTRIBUTES); // 3.x之前的版本使用
}
}
return distMap;
}
*/
}
/**
*
*/
package com.byd.info_platform.service.account;
import java.util.LinkedHashMap;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.byd.info_platform.entity.account.Resource;
/**
* 从数据库查询URL--授权定义Map的实现类.
*
*/
@Transactional(readOnly = true)
public class ResourceDetailsServiceImpl implements ResourceDetailsService {
private AccountManager accountManager;
/**
* @see ResourceDetailsService#getRequestMap()
*/
public LinkedHashMap<String, String> getRequestMap() throws Exception {//NOSONAR
List<Resource> resourceList = accountManager.getUrlResourceWithAuthorities();
LinkedHashMap<String, String> requestMap = new LinkedHashMap<String, String>(resourceList.size());
for (Resource resource : resourceList) {
requestMap.put(resource.getValue(), resource.getAuthNames());
}
return requestMap;
}
@Autowired
public void setAccountManager(AccountManager accountManager) {
this.accountManager = accountManager;
}
}