spring security3 扩展应用

spring security3

由于参与公司的一个项目用到了spring security3。开始以为ss3这种安全框架应该不会太难,可看了几天之后发现依旧不能运行出满足需求的demo出来。我去难道是我太笨了。又接着研究了一下终于大体上了解了spring security3 的用法。有不妥之处请各位大神指出

使用的spring security版本是3.0.8请大家注意一下

项目需求:将权限,资源和角色存储在数据库中。不能再配置文件中采用硬编码的形式配置。

如图所示的物理模型:

角色与用户为1:n的关系

角色与资源为n:n的关系

spring security3 扩展应用_第1张图片

创建数据库(mysql)

drop table if exists resources;

drop table if exists role_resource;

drop table if exists roles;

drop table if exists users;

/*==============================================================*/
/* Table: resources                                             */
/*==============================================================*/
create table resources
(
   rsid                 int not null auto_increment,
   rsurl                varchar(50) not null,
   primary key (rsid)
);

/*==============================================================*/
/* Table: role_resource                                         */
/*==============================================================*/
create table role_resource
(
   rid                  int not null,
   rsid                 int not null,
   primary key (rid, rsid)
);

/*==============================================================*/
/* Table: roles                                                 */
/*==============================================================*/
create table roles
(
   rid                  int not null auto_increment,
   rname                varchar(20) not null,
   rdescription         text,
   primary key (rid)
);

/*==============================================================*/
/* Table: users                                                 */
/*==============================================================*/
create table users
(
   uid                  int not null auto_increment,
   rid                  int not null,
   uenable              varchar(10) not null,
   uusername            varchar(50) not null,
   upassword            varchar(50) not null,
   uemail               varchar(50) not null,
   primary key (uid)
);


使用的数据库设计完成。官方提供了两张默认使用的数据库表结构用于在实现UserDetailsService类。用户装载用户名,密码和账户状态。如果使用默认数据库则不用扩展则可以实现

如果不使用默认的表结构则要扩展如下四个类:

 AbstractSecurityInterceptor 用于过滤URL。

UserDetailsService 用于装载用户信息。

FilterInvocationSecurityMetadataSource 用于获取URL所对应的权限

AccessDecisionManager 用于判断用户有没有权限访问。

首先让我们继承抽象类 AbstractSecurityInterceptor 代码如下

public class MySecurityInterceptor extends AbstractSecurityInterceptor implements Filter{
    private FilterInvocationSecurityMetadataSource securityMetadataSource;
	public void destroy() {
		
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		FilterInvocation filterInvocation = new FilterInvocation(request, response, chain);
		InterceptorStatusToken interceptorStatusToken = this.beforeInvocation(filterInvocation);
		filterInvocation.getChain().doFilter(request, response);
		this.afterInvocation(interceptorStatusToken, null);
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		
	}

	@Override
	public Class<? extends Object> getSecureObjectClass() {
		return FilterInvocation.class;
	}

	@Override
	public SecurityMetadataSource obtainSecurityMetadataSource() {
		return this.securityMetadataSource;
	}

	public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
		return securityMetadataSource;
	}

	public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
		this.securityMetadataSource = securityMetadataSource;
	}

}

 

实现FilterInvocationSecurityMetadataSource接口

public class MyInvocationSecurityMetadataSourceService implements
		FilterInvocationSecurityMetadataSource {
	private Map<String, Collection<ConfigAttribute>> map;
	private UrlMatcher urlMatcher = new AntUrlPathMatcher();
	public MyInvocationSecurityMetadataSourceService(JdbcTemplate jdbcTemplate){
		super();
		String sql = "select rname from roles";
		 List<Map<String, Object>> list = jdbcTemplate.queryForList(sql); 
		ConfigAttribute rolename = null;
		String urlsql = "";
		String url = "";
		Iterator<Map<String, Object>> iterator = list.iterator();
		map = new HashMap<String, Collection<ConfigAttribute>>();
		System.out.println(list.toString());
		while (iterator.hasNext()) {
			rolename = new SecurityConfig((String) iterator.next().get("rname"));
			urlsql = "select c.rsurl from roles a, role_resources b,resources c where a.rid=b.rid and b.rsid=c.rsid and a.rname="
					+ "'" + rolename.getAttribute() + "'";
			List<Map<String, Object>> list2 = jdbcTemplate.queryForList(urlsql);
			System.out.println(list2.toString());
			Iterator<Map<String, Object>> iterator2 = list2.iterator();
			while (iterator2.hasNext()) {
				url = (String) iterator2.next().get("rsurl");
				if (map.containsKey(url)) {
					Collection<ConfigAttribute> value = map.get(url);
					value.add(rolename);
					map.put(url, value);
				} else {
					Collection<ConfigAttribute> att = new ArrayList<ConfigAttribute>();
					att.add(rolename);
					map.put(url, att);
				}
			}
		}

	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		String url = ((FilterInvocation) object).getRequestUrl();
		int urlQuestionMarkIndex = url.indexOf("?");
		if (urlQuestionMarkIndex != -1) {
			url = url.substring(0, urlQuestionMarkIndex);
		}
		Iterator<String> iterator = map.keySet().iterator();
		String resurl = "";
		while (iterator.hasNext()) {
			resurl = iterator.next();
			if (urlMatcher.pathMatchesUrl(url, resurl)) {
				System.out.print(",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,");
				System.out.println(map.get(url).toString());
				return map.get(url);
			}
		}
		return null;
	}

	public boolean supports(Class<?> arg0) {
		return true;
	}

}


实现UserDetailsService接口

public class AccessDecisionManager implements org.springframework.security.access.AccessDecisionManager{

	public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
			InsufficientAuthenticationException {
		    if (configAttributes==null) return;
            Iterator<ConfigAttribute> iterator = configAttributes.iterator();
            while(iterator.hasNext()){
            	ConfigAttribute configAttribute = iterator.next();
            	String needRole = ((SecurityConfig)configAttribute).getAttribute();
            	System.out.println("///////////////////////////////////////");
            	System.out.println(needRole);
            	System.out.println(object.getClass().getName());
            	for(GrantedAuthority ga : authentication.getAuthorities()){
            		if(needRole.equals(ga.getAuthority())){
            			System.out.println(ga.getAuthority());
            			return ;
            		}
            	}
            }
            throw new AccessDeniedException("没有权限");
	}

	public boolean supports(ConfigAttribute arg0) {
		return true;
	}

	public boolean supports(Class<?> arg0) {
		return true;
	}

}


实现AccessDecisionManager接口

public class AccessDecisionManager implements org.springframework.security.access.AccessDecisionManager{

	public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
			InsufficientAuthenticationException {
		    if (configAttributes==null) return;
            Iterator<ConfigAttribute> iterator = configAttributes.iterator();
            while(iterator.hasNext()){
            	ConfigAttribute configAttribute = iterator.next();
            	String needRole = ((SecurityConfig)configAttribute).getAttribute();
            	System.out.println("///////////////////////////////////////");
            	System.out.println(needRole);
            	System.out.println(object.getClass().getName());
            	for(GrantedAuthority ga : authentication.getAuthorities()){
            		if(needRole.equals(ga.getAuthority())){
            			System.out.println(ga.getAuthority());
            			return ;
            		}
            	}
            }
            throw new AccessDeniedException("没有权限");
	}

	public boolean supports(ConfigAttribute arg0) {
		return true;
	}

	public boolean supports(Class<?> arg0) {
		return true;
	}

}

下面是配置文件

<?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-3.0.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.0.xsd">

	<http auto-config='true' access-denied-page="/accessDenied。jsp" use-expressions="true">
		<form-login login-page="/login.jsp" />
		<logout logout-success-url="/login.jsp" />
		<intercept-url pattern="/login.jsp*" filters="none" />
	     <intercept-url pattern="/**" access="isAuthenticated()" />
		<session-management invalid-session-url="/sessionTimeout.jsp">
		</session-management>
		<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR" />
	</http>

	<authentication-manager alias="authenticationManager">
		<authentication-provider user-service-ref="userDetailsManager">
		</authentication-provider>
	</authentication-manager>

	<beans:bean id="userDetailsManager"
		class="com.xiaoqiang.userdetailsservice.MyUserDetailsService">
		<beans:property name="myJdbcTemplate" ref="jdbcTemplate"></beans:property>
		</beans:bean>

	<beans:bean id="myFilter"
		class="com.xiaoqiang.abstractsecurityinterceptor.MySecurityInterceptor">
		<beans:property name="authenticationManager" ref="authenticationManager" />
		<beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />
		<beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />
	</beans:bean>

	<beans:bean id="myAccessDecisionManager"
		class="com.xiaoqiang.accessdecisionmanager.AccessDecisionManager">
	</beans:bean>

	<beans:bean id="mySecurityMetadataSource"
		class="com.xiaoqiang.securitymetadatasource.MyInvocationSecurityMetadataSourceService">
		<beans:constructor-arg index="0" ref="jdbcTemplate"></beans:constructor-arg>
	</beans:bean>

	<beans:bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<beans:property name="basename" value="classpath:message_zh_CN" />
	</beans:bean>

	<beans:bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<beans:property name="dataSource" ref="dataSource"></beans:property>
	</beans:bean>
	<beans:bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<beans:property name="driverClassName" value="com.mysql.jdbc.Driver"></beans:property>
		<beans:property name="url" value="jdbc:mysql://localhost:3306/test1"></beans:property>
		<beans:property name="username" value="root"></beans:property>
		<beans:property name="password" value="ragedream"></beans:property>
	</beans:bean>
</beans:beans>

配置完成

你可能感兴趣的:(java,spring,spring,Security)