spring security
配置过滤器
首先要在web.xml中配置过滤器,这样我们就可以控制对这个项目的每个请求了
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
所有的用户在访问项目之前,都要先通过Spring Security的检测,这从第一时间把没有授权的请求排除在系统之外,保证系统资源的安全。
命名空间
<?xml version="1.0"encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
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.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
</beans:beans>
基本配置
<!--定义认证管理器-->
<authentication-manageralias="authenticationManager" />
<authentication-manageralias="authenticationManager"
session-controller-ref="concurrentSessionController"/>
<beans:beanid="sessionRegistry"
class="org.springframework.security.concurrent.SessionRegistryImpl"/>
<beans:beanid="concurrentSessionController"
class="org.springframework.security.concurrent.ConcurrentSessionControllerImpl">
<beans:propertyname="maximumSessions" value="1" />
<beans:propertyname="exceptionIfMaximumExceeded" value="false" />
<beans:propertyname="sessionRegistry" ref="sessionRegistry" />
</beans:bean>
<http auto-config='true'lowercase-comparisons="false"
access-denied-page="/System/Login.action?error=true">
<intercept-urlpattern="/System/Login.action" filters="none" />
<intercept-urlpattern="/System/Login!logout.action" filters="none"/>
<form-loginlogin-page="/System/Login.action"
default-target-url="/System/Login!login.action"
login-processing-url="/System/j_login_check"
authentication-failure-url="/System/Login.action"
always-use-default-target="true"/>
<concurrent-session-control expired-url="/System/Login.action" max-sessions="1" />
<logout logout-success-url="/System/Login!logout.action" invalidate-session="true"
logout-url="/System/j_spring_security_logout"/>
</http>
<!--认证数据提供者-->
<authentication-provideruser-service-ref="userDetailsService" />
<beans:beanid="userDetailsService" class="com.***.security.UserDetailsServiceImpl">
<beans:propertyname="***" ref="UsermCache" />
<beans:propertyname="***" ref="UserRoleCache"/>
<beans:propertyname=***" ref="UserMenuCache"/>
</beans:bean>
<!--访问决策管理器-->
<beans:bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
<beans:propertyname="decisionVoters">
<beans:list>
<beans:bean class="org.springframework.security.vote.RoleVoter">
<beans:propertyname="rolePrefix" value="ROLE_" />
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
<!--过滤器安全拦截器,检查authentication所授予的权限是否可以访问被访问的资源-->
<beans:beanid="filterSecurityInterceptor" class="com.***.security.RefreshResources">
<!--覆盖http配置中的intercept-url的配置-->
<custom-filterbefore="FILTER_SECURITY_INTERCEPTOR" />
<beans:propertyname="authenticationManager" ref="authenticationManager"/>
<beans:propertyname="accessDecisionManager" ref="accessDecisionManager"/>
<beans:propertyname="PermissionService"ref="PermissionService" />
</beans:bean>
<beans:beanid="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basename" value="classpath:com/***/web/action/system/LoginAction"/>
</beans:bean>
<beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"/>
配置好的AuthenticationManager会处理每个认证请求。如果认证失败,浏览器会重定向到authenticationFailureUrl。AuthenticationException会被放到HttpSession中,属性名是AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY,在错误页里为用户提供一个出错原因。
maximumSessions属性配置了只允许同一个用户登录系统一次,exceptionIfMaximumExceeded属性配置了在进行第二次登录是是否让第一次登录失效。这里设置为true不允许第二次登录。要让此功能生效,我们还需要在web.xml文件中添加一个监听器,以让Spring Security能获取Session的生命周期事件,配置如下:
<listener>
<listener-class>
org.springframework.security.ui.session.HttpSessionEventPublisher
</listener-class>
</listener>
concurrentSessionController使用sessionRegistry来完成对发布的Session的生命周期事件的处理,org.springframework.security.concurrent.SessionRegistryImpl(实现了 SessionRegistry接口), SessionRegistryImpl类还实现了Spring Framework的事件监听org.springframework.context.Application Listener接口,并实现了该接口定义的onApplicationEvent(ApplicationEvent event)方法用于处理Applic ationEvent类型的事件
<http>
<http auto-config='true'lowercase-comparisons="false"
access-denied-page="/System/SystemLogin.shtml?error=true" access-decision-manager-ref="accessDecisionManager">
auto-config='true'将自动配置几种常用的权限控制机制
lowercase-comparisons:表示URL比较前先转为小写
access-denied-page:访问拒绝时转向的页面
access-decision-manager-ref:指定了自定义的访问策略管理器。当系统角色名的前缀不是默认的ROLE_时,需要自定义访问策略管理器
<form-login >
<form-login login-page="/System/Login.action" default-target-url="/System/Login!login.action"
login-processing-url="/System/j_login_check" authentication-failure-url="/System/SystemLogin.action" always-use-default-target="true" />
login-page:指定登录页面(登录表单包含j_username和 j_password输入框)
login-processing-url:指定了客户在登录页面中按下 Sign In按钮时要访问的 URL。与登录页面form的action一致。其默认值为:/j_spring_security_check。
authentication-failure-url:指定了身份验证失败时跳转到的页面
default-target-url:指定了成功进行身份验证和授权后默认呈现给用户的页面
always-use-default-target:指定了是否在身份验证通过后总是跳转到default-target-url
j_username,输入登陆名的参数名称。
j_password,输入密码的参数名称
_spring_security_remember_me,选择是否允许自动登录的参数名称。
<logout>
<logout logout-success-url="/System/Login!logout.action" invalidate-session="true"
logout-url="/System/j_spring_security_logout"/>
logout-url:指定了用于响应退出系统请求的URL。其默认值为:/j_spring_security_logout。
logout-success-url:退出系统后转向的URL。
invalidate-session:指定在退出系统时是否要销毁Session。
<concurrent-session-control>
<concurrent-session-controlexpired-url="/System/Login.action" max-sessions="1"/>
max-sessions:允许用户帐号登录的次数。范例限制用户只能登录一次。
exception-if-maximum-exceeded:
默认为false,此值表示:用户第二次登录时,前一次的登录信息都被清空。
当exception-if-maximum-exceeded="true"时系统会拒绝第二次登录。
expired-url :session失效后跳转的页面
<authentication-manageralias="authenticationManager" />
<!--
<authentication-manageralias="authenticationManager"
session-controller-ref="concurrentSessionController"/>
<beans:beanid="sessionRegistry"
class="org.springframework.security.concurrent.SessionRegistryImpl"/>
<beans:beanid="concurrentSessionController"
class="org.springframework.security.concurrent.ConcurrentSessionControllerImpl">
<beans:propertyname="maximumSessions" value="1" />
<beans:propertyname="exceptionIfMaximumExceeded" value="false" />
<beans:propertyname="sessionRegistry" ref="sessionRegistry" />
</beans:bean>
-->
<!--访问决策管理器1-->
<b:bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
<b:property name="allowIfAllAbstainDecisions"value="false"/>
<!--设定是否允许"没人反对就通过"的投票策略 -->
<b:property name="decisionVoters"><!--投票者 -->
<b:list>
<b:beanclass="org.springframework.security.vote.RoleVoter">
<b:propertyname="rolePrefix" value=""/>
<!--投票者支持的权限前缀,默认是“ROLE_” -->
</b:bean>
</b:list>
</b:property>
</b:bean>
<!--访问决策管理器2-->
<beans:beanid="accessDecisionManager"
class="org.springframework.security.vote.AffirmativeBased">
<beans:propertyname="decisionVoters">
<beans:list>
<beans:bean
class="org.springframework.security.vote.RoleVoter">
<beans:propertyname="rolePrefix" value="ROLE_" />
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
Spring security提供三种投票通过策略的实现:
1、AffirmativeBased(至少一个投票者同意方可通过)
2、ConsensusBased(多数投票者同意方可通过)
3、UnanimousBased(所有投票者同意方可通过)
<authentication-provider>
DAO身份验证提供者的配置
<authentication-provider user-service-ref="userDetailsService"/>
<beans:beanid="userDetailsService"
class="com.***.security.UserDetailsServiceImpl">
<beans:propertyname="UsermCache" ref="UsermCache" />
<beans:propertyname="UserRoleCache" ref="UserRoleCache"/>
<beans:propertyname="UserMenuCache" ref="UserMenuCache"/>
</beans:bean>
<!--过滤器安全拦截器,负责授权的filter,检查authentication所授予的权限是否可以访问被访问的资源-->
<beans:beanid="filterSecurityInterceptor"class="com.***.security.RefreshResources">
<!--覆盖http配置中的intercept-url的配置-->
<custom-filterbefore="FILTER_SECURITY_INTERCEPTOR" />
<beans:propertyname="authenticationManager" ref="authenticationManager"/>
<beans:propertyname="accessDecisionManager" ref="accessDecisionManager"/>
<beans:propertyname="PermissionService"ref="PermissionService" />
</beans:bean>
private static FilterInvocationDefinitionSource s = null;
private static boolean flag = true;
/**=============================================get/set=============================================*/
// SystemPermissionService
private SystemPermissionService systemPermissionService;
public SystemPermissionService getSystemPermissionService()
{
return systemPermissionService;
}
public void setSystemPermissionService(
SystemPermissionService systemPermissionService)
{
this.systemPermissionService = systemPermissionService;
}
/**=============================================主方法=============================================*/
@SuppressWarnings("unchecked")
@Override
public ObjectDefinitionSource obtainObjectDefinitionSource()
{
if (s == null)
{
if (flag)
{
try
{
systemPermissionService.cacheInitialization();
}
catch (CacheException e)
{
loger.error(e);
}
}
Map<String, String> resourceMap = systemPermissionService.listResourceMap();
UrlMatcher urlMatcher = null;
LinkedHashMap requestMap = null;
ConfigAttributeEditor editor = null;
if (null != resourceMap && !resourceMap.isEmpty())
{
editor = new ConfigAttributeEditor();
requestMap = new LinkedHashMap<RequestKey, ConfigAttributeDefinition>();
for (Map.Entry<String, String> entry : resourceMap.entrySet())
{
RequestKey key = new RequestKey(entry.getKey(), null);
editor.setAsText(entry.getValue());
requestMap.put(key, (ConfigAttributeDefinition) editor
.getValue());
}
}
if (null != requestMap && !requestMap.isEmpty())
{
urlMatcher = new AntUrlPathMatcher(true);
s = new DefaultFilterInvocationDefinitionSource(urlMatcher,
requestMap);
}
}
return s;
}
public static void refresh()
{
s = null;
flag = false;
}
配置过滤器
首先要在web.xml中配置过滤器,这样我们就可以控制对这个项目的每个请求了
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
所有的用户在访问项目之前,都要先通过Spring Security的检测,这从第一时间把没有授权的请求排除在系统之外,保证系统资源的安全。
命名空间
<?xml version="1.0"encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
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.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
</beans:beans>
基本配置
<!--定义认证管理器-->
<authentication-manageralias="authenticationManager" />
<authentication-manageralias="authenticationManager"
session-controller-ref="concurrentSessionController"/>
<beans:beanid="sessionRegistry"
class="org.springframework.security.concurrent.SessionRegistryImpl"/>
<beans:beanid="concurrentSessionController"
class="org.springframework.security.concurrent.ConcurrentSessionControllerImpl">
<beans:propertyname="maximumSessions" value="1" />
<beans:propertyname="exceptionIfMaximumExceeded" value="false" />
<beans:propertyname="sessionRegistry" ref="sessionRegistry" />
</beans:bean>
<http auto-config='true'lowercase-comparisons="false"
access-denied-page="/System/Login.action?error=true">
<intercept-urlpattern="/System/Login.action" filters="none" />
<intercept-urlpattern="/System/Login!logout.action" filters="none"/>
<form-loginlogin-page="/System/Login.action"
default-target-url="/System/Login!login.action"
login-processing-url="/System/j_login_check"
authentication-failure-url="/System/Login.action"
always-use-default-target="true"/>
<concurrent-session-control expired-url="/System/Login.action" max-sessions="1" />
<logout logout-success-url="/System/Login!logout.action" invalidate-session="true"
logout-url="/System/j_spring_security_logout"/>
</http>
<!--认证数据提供者-->
<authentication-provideruser-service-ref="userDetailsService" />
<beans:beanid="userDetailsService" class="com.***.security.UserDetailsServiceImpl">
<beans:propertyname="***" ref="UsermCache" />
<beans:propertyname="***" ref="UserRoleCache"/>
<beans:propertyname=***" ref="UserMenuCache"/>
</beans:bean>
<!--访问决策管理器-->
<beans:bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
<beans:propertyname="decisionVoters">
<beans:list>
<beans:bean class="org.springframework.security.vote.RoleVoter">
<beans:propertyname="rolePrefix" value="ROLE_" />
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
<!--过滤器安全拦截器,检查authentication所授予的权限是否可以访问被访问的资源-->
<beans:beanid="filterSecurityInterceptor" class="com.***.security.RefreshResources">
<!--覆盖http配置中的intercept-url的配置-->
<custom-filterbefore="FILTER_SECURITY_INTERCEPTOR" />
<beans:propertyname="authenticationManager" ref="authenticationManager"/>
<beans:propertyname="accessDecisionManager" ref="accessDecisionManager"/>
<beans:propertyname="PermissionService"ref="PermissionService" />
</beans:bean>
<beans:beanid="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basename" value="classpath:com/***/web/action/system/LoginAction"/>
</beans:bean>
<beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"/>
配置好的AuthenticationManager会处理每个认证请求。如果认证失败,浏览器会重定向到authenticationFailureUrl。AuthenticationException会被放到HttpSession中,属性名是AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY,在错误页里为用户提供一个出错原因。
maximumSessions属性配置了只允许同一个用户登录系统一次,exceptionIfMaximumExceeded属性配置了在进行第二次登录是是否让第一次登录失效。这里设置为true不允许第二次登录。要让此功能生效,我们还需要在web.xml文件中添加一个监听器,以让Spring Security能获取Session的生命周期事件,配置如下:
<listener>
<listener-class>
org.springframework.security.ui.session.HttpSessionEventPublisher
</listener-class>
</listener>
concurrentSessionController使用sessionRegistry来完成对发布的Session的生命周期事件的处理,org.springframework.security.concurrent.SessionRegistryImpl(实现了 SessionRegistry接口), SessionRegistryImpl类还实现了Spring Framework的事件监听org.springframework.context.Application Listener接口,并实现了该接口定义的onApplicationEvent(ApplicationEvent event)方法用于处理Applic ationEvent类型的事件
<http>
<http auto-config='true'lowercase-comparisons="false"
access-denied-page="/System/SystemLogin.shtml?error=true" access-decision-manager-ref="accessDecisionManager">
auto-config='true'将自动配置几种常用的权限控制机制
lowercase-comparisons:表示URL比较前先转为小写
access-denied-page:访问拒绝时转向的页面
access-decision-manager-ref:指定了自定义的访问策略管理器。当系统角色名的前缀不是默认的ROLE_时,需要自定义访问策略管理器
<form-login >
<form-login login-page="/System/Login.action" default-target-url="/System/Login!login.action"
login-processing-url="/System/j_login_check" authentication-failure-url="/System/SystemLogin.action" always-use-default-target="true" />
login-page:指定登录页面(登录表单包含j_username和 j_password输入框)
login-processing-url:指定了客户在登录页面中按下 Sign In按钮时要访问的 URL。与登录页面form的action一致。其默认值为:/j_spring_security_check。
authentication-failure-url:指定了身份验证失败时跳转到的页面
default-target-url:指定了成功进行身份验证和授权后默认呈现给用户的页面
always-use-default-target:指定了是否在身份验证通过后总是跳转到default-target-url
j_username,输入登陆名的参数名称。
j_password,输入密码的参数名称
_spring_security_remember_me,选择是否允许自动登录的参数名称。
<logout>
<logout logout-success-url="/System/Login!logout.action" invalidate-session="true"
logout-url="/System/j_spring_security_logout"/>
logout-url:指定了用于响应退出系统请求的URL。其默认值为:/j_spring_security_logout。
logout-success-url:退出系统后转向的URL。
invalidate-session:指定在退出系统时是否要销毁Session。
<concurrent-session-control>
<concurrent-session-controlexpired-url="/System/Login.action" max-sessions="1"/>
max-sessions:允许用户帐号登录的次数。范例限制用户只能登录一次。
exception-if-maximum-exceeded:
默认为false,此值表示:用户第二次登录时,前一次的登录信息都被清空。
当exception-if-maximum-exceeded="true"时系统会拒绝第二次登录。
expired-url :session失效后跳转的页面
<authentication-manageralias="authenticationManager" />
<!--
<authentication-manageralias="authenticationManager"
session-controller-ref="concurrentSessionController"/>
<beans:beanid="sessionRegistry"
class="org.springframework.security.concurrent.SessionRegistryImpl"/>
<beans:beanid="concurrentSessionController"
class="org.springframework.security.concurrent.ConcurrentSessionControllerImpl">
<beans:propertyname="maximumSessions" value="1" />
<beans:propertyname="exceptionIfMaximumExceeded" value="false" />
<beans:propertyname="sessionRegistry" ref="sessionRegistry" />
</beans:bean>
-->
<!--访问决策管理器1-->
<b:bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
<b:property name="allowIfAllAbstainDecisions"value="false"/>
<!--设定是否允许"没人反对就通过"的投票策略 -->
<b:property name="decisionVoters"><!--投票者 -->
<b:list>
<b:beanclass="org.springframework.security.vote.RoleVoter">
<b:propertyname="rolePrefix" value=""/>
<!--投票者支持的权限前缀,默认是“ROLE_” -->
</b:bean>
</b:list>
</b:property>
</b:bean>
<!--访问决策管理器2-->
<beans:beanid="accessDecisionManager"
class="org.springframework.security.vote.AffirmativeBased">
<beans:propertyname="decisionVoters">
<beans:list>
<beans:bean
class="org.springframework.security.vote.RoleVoter">
<beans:propertyname="rolePrefix" value="ROLE_" />
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
Spring security提供三种投票通过策略的实现:
1、AffirmativeBased(至少一个投票者同意方可通过)
2、ConsensusBased(多数投票者同意方可通过)
3、UnanimousBased(所有投票者同意方可通过)
<authentication-provider>
DAO身份验证提供者的配置
<authentication-provider user-service-ref="userDetailsService"/>
<beans:beanid="userDetailsService"
class="com.***.security.UserDetailsServiceImpl">
<beans:propertyname="UsermCache" ref="UsermCache" />
<beans:propertyname="UserRoleCache" ref="UserRoleCache"/>
<beans:propertyname="UserMenuCache" ref="UserMenuCache"/>
</beans:bean>
<!--过滤器安全拦截器,负责授权的filter,检查authentication所授予的权限是否可以访问被访问的资源-->
<beans:beanid="filterSecurityInterceptor"class="com.***.security.RefreshResources">
<!--覆盖http配置中的intercept-url的配置-->
<custom-filterbefore="FILTER_SECURITY_INTERCEPTOR" />
<beans:propertyname="authenticationManager" ref="authenticationManager"/>
<beans:propertyname="accessDecisionManager" ref="accessDecisionManager"/>
<beans:propertyname="PermissionService"ref="PermissionService" />
</beans:bean>
private static FilterInvocationDefinitionSource s = null;
private static boolean flag = true;
/**=============================================get/set=============================================*/
// SystemPermissionService
private SystemPermissionService systemPermissionService;
public SystemPermissionService getSystemPermissionService()
{
return systemPermissionService;
}
public void setSystemPermissionService(
SystemPermissionService systemPermissionService)
{
this.systemPermissionService = systemPermissionService;
}
/**=============================================主方法=============================================*/
@SuppressWarnings("unchecked")
@Override
public ObjectDefinitionSource obtainObjectDefinitionSource()
{
if (s == null)
{
if (flag)
{
try
{
systemPermissionService.cacheInitialization();
}
catch (CacheException e)
{
loger.error(e);
}
}
Map<String, String> resourceMap = systemPermissionService.listResourceMap();
UrlMatcher urlMatcher = null;
LinkedHashMap requestMap = null;
ConfigAttributeEditor editor = null;
if (null != resourceMap && !resourceMap.isEmpty())
{
editor = new ConfigAttributeEditor();
requestMap = new LinkedHashMap<RequestKey, ConfigAttributeDefinition>();
for (Map.Entry<String, String> entry : resourceMap.entrySet())
{
RequestKey key = new RequestKey(entry.getKey(), null);
editor.setAsText(entry.getValue());
requestMap.put(key, (ConfigAttributeDefinition) editor
.getValue());
}
}
if (null != requestMap && !requestMap.isEmpty())
{
urlMatcher = new AntUrlPathMatcher(true);
s = new DefaultFilterInvocationDefinitionSource(urlMatcher,
requestMap);
}
}
return s;
}
public static void refresh()
{
s = null;
flag = false;
}