使用Spring Security3的几种方法概述
一种是全部利用配置文件,将用户、权限、资源(url)硬编码在xml文件中,已经实现过。
二种是用户和权限用数据库存储,而资源(url)和权限的对应采用硬编码配置,目前这种方式已经实现。
三种我使用的是第三种 第三种是细分角色和权限,并将用户、角色、权限和资源均采用数据库存储,并且自定义过滤器,代替原有的FilterSecurityInterceptor过滤器,
并分别实现AccessDecisionManager、InvocationSecurityMetadataSourceService和UserDetailsService,并在配置文件中进行相应配置。
四种第四种方式我没有试过 。
业务逻辑
权限代码action为请求路径,权限信息拥有多个权限代码,角色可以拥有多个权限信息, 用户属于用户组,用户组拥有多个角色,用户组必须拥有跟菜单同样权限代码action、页面菜单才能显示 , 最终实现菜单显示与请求路径权限验证。
在上个项目开发中用到的技术: java1.5 + struts2.1.8 + spring3.0.7 + hibernate3.2.5 + spring security3.1.0 + mysql5.5 + tomcat6.0。
我这里只说明spring security,代码是项目里抽取权限部分出来讲解的,
spring security3.1 .0 的11 个jar包,分别为:
spring-security-acl-3.1 .0 .RELEASE.jar
spring-security-config-3.1 .0 .RELEASE.jar
spring-security-core-3.1 .0 .RELEASE.jar
spring-security-taglibs-3.1 .0 .RELEASE.jar
spring-security-web-3.1 .0 .RELEASE.jar
spring-security-aspects-3.1.0.RELEASE.jar
spring-security-cas-3.1.0.RELEASE.jar
spring-security-crypto-3.1.0.RELEASE.jar
spring-security-ldap-3.1.0.RELEASE.jar
spring-security-openid-3.1.0.RELEASE.jar
spring-security-remoting-3.1.0.RELEASE.jar
当然还有其他项目相关 的jar包,不贴出来了 。
年初讲解过spring security的旧版本Acegi的文章xml配置稍微复杂一些, spring security3配置相对比较简单。
Spring Security3 配置使用
1 spring security3 主要实现类。
2 spring security3 主要配置文件。
3 web.xml配置文件。
4 实现流程说明
5 权限sql脚本
6 附件为完整程序与数据库脚本
1、spring security3 主要实现类 (包含4个关键类):
myFilter
(1) MySecurityFilter.java 过滤用户请求
- package com.taskmanager.web.security;
- import java.io.IOException;
- import java.util.Collection;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import org.springframework.security.access.ConfigAttribute;
- import org.springframework.security.access.SecurityMetadataSource;
- import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
- import org.springframework.security.access.intercept.InterceptorStatusToken;
- import org.springframework.security.web.FilterInvocation;
- import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
- public class MySecurityFilter extends AbstractSecurityInterceptor implements
- Filter {
- // 与applicationContext-security.xml里的myFilter的属性securityMetadataSource对应,
- // 其他的两个组件,已经在AbstractSecurityInterceptor定义
- private FilterInvocationSecurityMetadataSource securityMetadataSource;
- @Override
- public SecurityMetadataSource obtainSecurityMetadataSource() {
- return this.securityMetadataSource;
- }
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- FilterInvocation fi = new FilterInvocation(request, response, chain);
- invoke(fi);
- }
- private void invoke(FilterInvocation fi) throws IOException,
- ServletException {
- // object为FilterInvocation对象
- // super.beforeInvocation(fi);//源码
- // 1.获取请求资源的权限
- //执行 Collection<ConfigAttribute> attributes =
- //securityMetadataSource.getAttributes(fi);
- // 2.是否拥有权限
- // this.accessDecisionManager.decide(authenticated, fi, attributes);
- // this.accessDecisionManager.decide(authenticated, fi, attributes);
- InterceptorStatusToken token = super.beforeInvocation(fi);
- try {
- fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
- } finally {
- super.afterInvocation(token, null);
- }
- }
- public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
- return securityMetadataSource;
- }
- public void setSecurityMetadataSource(
- FilterInvocationSecurityMetadataSource securityMetadataSource) {
- this.securityMetadataSource = securityMetadataSource;
- }
- public void init(FilterConfig arg0) throws ServletException {
- // TODO Auto-generated method stub
- }
- public void destroy() {
- // TODO Auto-generated method stub
- }
- @Override
- public Class<? extends Object> getSecureObjectClass() {
- //下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误
- return FilterInvocation.class;
- }
- }
package com.taskmanager.web.security;
import java.io.IOException;
import java.util.Collection;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
public class MySecurityFilter extends AbstractSecurityInterceptor implements
Filter {
// 与applicationContext-security.xml里的myFilter的属性securityMetadataSource对应,
// 其他的两个组件,已经在AbstractSecurityInterceptor定义
private FilterInvocationSecurityMetadataSource securityMetadataSource;
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
}
private void invoke(FilterInvocation fi) throws IOException,
ServletException {
// object为FilterInvocation对象
// super.beforeInvocation(fi);//源码
// 1.获取请求资源的权限
//执行 Collection<ConfigAttribute> attributes =
//securityMetadataSource.getAttributes(fi);
// 2.是否拥有权限
// this.accessDecisionManager.decide(authenticated, fi, attributes);
// this.accessDecisionManager.decide(authenticated, fi, attributes);
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return securityMetadataSource;
}
public void setSecurityMetadataSource(
FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
}
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public Class<? extends Object> getSecureObjectClass() {
//下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误
return FilterInvocation.class;
}
}
核心的InterceptorStatusToken token = super.beforeInvocation(fi);会调用我们定义的accessDecisionManager:decide(Object object)和securityMetadataSource
:getAttributes(Object object)方法。