spring security3.2.0简单配置

最近学习了下spring security,现在的最新版本是spring security3.2.0。搞了好长时间看了好多博文,以及官方文档终于整出了一个小例子了。在这里帖出来,希望能给大家一个参考,并且我也可以时常回顾。


一.数据库表结构

表结构采用 用户-角色-资源的权限管理设计

运用的是MySql数据库。

1.用户表users

create table if not exists user(
  id bigint not null auto_increment,
  username varchar(50),
  password varchar(50),
  status integer,
  descn varchar(200),
  primary key(id)
);


2.角色表role

create table if not exists role(
  id bigint not null auto_increment,
  name varchar(50),
  descn varchar(200),
  primary key(id)
);


3.资源表resc

create table if not exists resc(
  id bigint not null auto_increment,
  name varchar(50),
  res_type varchar(50),
  res_string varchar(200),
  descn varchar(200),
  primary key(id)
);


4.用户角色关联表user_role

create table if not exists user_role(
  user_id bigint,
  role_id bigint,
  foreign key(user_id) references user(id) on delete cascade on update cascade,
  foreign key(role_id) references role(id) on delete cascade on update cascade
);

5.角色资源关联表resc_role
create table if not exists resc_role(
  resc_id bigint,
  role_id bigint,
  foreign key(resc_id) references resc(id) on delete cascade on update cascade,
  foreign key(role_id) references role(id) on delete cascade on update cascade
);


插入数据

insert into user(username,password,status,descn) values('admin','admin',1,'管理员');
insert into user(username,password,status,descn) values('user','user',1,'用户');

insert into role(name,descn) values('ROLE_ADMIN','管理员角色');
insert into role(name,descn) values('ROLE_USER','用户角色');

insert into resc(id,name,res_type,res_string,descn) values(1,'','URL','/admin.jsp','');
insert into resc(id,name,res_type,res_string,descn) values(2,'','URL','/**','');


insert into resc_role(resc_id,role_id) values(1,1);
insert into resc_role(resc_id,role_id) values(2,1);
insert into resc_role(resc_id,role_id) values(2,2);
insert into user_role(user_id,role_id) values(1,1);
insert into user_role(user_id,role_id) values(1,2);
insert into user_role(user_id,role_id) values(2,2);


二.系统配置文件

1)web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">

	<display-name>spring_security</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:/applicationContext*.xml</param-value>
	</context-param>
	
	<!-- 指定Log4J配置文件位置 -->
	<context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>/WEB-INF/log4j.properties</param-value>
	</context-param>
	
	<listener>
	    <!-- 负责加载 log4j监听器 -->
	    <listener-class>
	        org.springframework.web.util.Log4jConfigListener
	    </listener-class>
	</listener>
	<listener>
		<!-- 负责加载 classpath:applicationContext -->
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	
	<listener>
	    <!-- 负责加载会话监听器事件 -->
    	<listener-class>
      	    org.springframework.security.web.session.HttpSessionEventPublisher
    	</listener-class>
    </listener>
	
	<!-- 负责加载spring security过滤器 -->
	<filter>
	    <filter-name>springSecurityFilterChain</filter-name>
	    <filter-class>
	        org.springframework.web.filter.DelegatingFilterProxy
	    </filter-class>
	    <init-param>
	        <param-name>target-class</param-name>
	        <param-value>org.springframework.security.web.FilterChainProxy</param-value>
	    </init-param>
	</filter>
	<filter-mapping>
	    <filter-name>springSecurityFilterChain</filter-name>
	    <url-pattern>/*</url-pattern>
	</filter-mapping>

	<filter>
		<filter-name>setCharacterEncoding</filter-name>
		<filter-class>
			org.springframework.web.filter.CharacterEncodingFilter
		</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter><!-- filtered type -->
	<filter-mapping>
		<filter-name>setCharacterEncoding</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
	<!-- 系统欢迎界面 -->
	<welcome-file-list>
	    <welcome-file>login.jsp</welcome-file>
	</welcome-file-list>


</web-app>

 


该文件用于在容器启动时自动加载spring security的过滤器,用来过滤所有的用户请求


2)applicationContext-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- - Application context containing authentication, channel - security 
	and web URI beans. - - Only used by "filter" artifact. - -->

<b:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	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.1.xsd">

    
    <!-- 不要过滤图片等静态资源 -->
    <http pattern="/**/*.jpg" security="none"/>
    <http pattern="/**/*.png" security="none"/>
    <http pattern="/**/*.gif" security="none"/>
    <http pattern="/**/*.css" security="none"/>
    <http pattern="/**/*.js" security="none"/>
    
    <!-- 这个元素用来在你的应用程序中启用基于安全的注解 
    <global-method-security  pre-post-annotations="enabled" access-decision-manager-ref="myAccessDecisionManager"/>
    -->
    
    
	<!-- 配置页面访问权限 -->
	<http auto-config='true' access-denied-page="/accessDenied.jsp">
	    
		<!-- 登陆页面和忘记密码页面不过滤 -->
		<intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
		<intercept-url pattern="/forgotpassword.jsp"/>
		
		<form-login login-page="/login.jsp"
			authentication-failure-url="/login.jsp?error=true"
			default-target-url="/index.jsp" always-use-default-target='true' />
		
		<!-- "记住我"功能,采用持久化策略(将用户的登录信息存放在数据库表中) -->
		<remember-me data-source-ref="dataSource" />
		
		<!-- 实现免登陆验证 -->
		<!-- 只能登陆一次 -->
		<session-management
			session-authentication-error-url="/402.jsp" invalid-session-url="/sessionTimeout.jsp">
			<concurrency-control max-sessions="1"
				error-if-maximum-exceeded="true" />
		</session-management>
		
		<logout/>

		<!-- 增加一个自定义的filter,放在FILTER_SECURITY_INTERCEPTOR之前,
		实现用户、角色、权限、资源的数据库管理。 11/3/23 -->
		<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/> 
	</http>

	<!-- 将用户信息硬编码在xml文件中 -->
	<!-- <authentication-manager> <authentication-provider> <user-service> <user 
		name="admin" password="admin" authorities="ROLE_ADMIN,ROLE_USER" /> <user 
		name="user" password="user" authorities="ROLE_USER" /> </user-service> </authentication-provider> 
		</authentication-manager> -->

	<!-- 数据中查找用户 
	<authentication-manager alias="myAuthenticationManager">
		<authentication-provider>
			<jdbc-user-service data-source-ref="dataSource"
				users-by-username-query="select username,password,status as enabled
                               from user
                              where username=?"
				authorities-by-username-query="select u.username,r.name as authority
                                             from user u
                                     join user_role ur
                                    on u.id=ur.user_id
                                      join role r
                                    on r.id=ur.role_id
                                     where u.username=?" />
		</authentication-provider>
	</authentication-manager>
	-->


	<!-- 实现了UserDetailsService的Bean -->
	<!-- 注意能够为authentication-manager 设置alias别名 -->
	<authentication-manager alias="myAuthenticationManager">
		<authentication-provider user-service-ref="myUserDetailService">
		   
			<password-encoder ref="passwordEncoder">
				<salt-source user-property="username" />
			</password-encoder>
			 
		</authentication-provider>
	</authentication-manager>

	<!-- 一个自定义的filter,必须包含authenticationManager, accessDecisionManager,securityMetadataSource三个属性。 -->
	<b:bean id="myFilter"
		class="com.spring.security.filter.MyFilterSecurityInterceptor">
		<!-- 用户拥有的权限 -->
		<b:property name="authenticationManager" ref="myAuthenticationManager"></b:property>
		<!-- 用户是否拥有所请求资源的权限 -->
		<b:property name="accessDecisionManager" ref="myAccessDecisionManager"></b:property>
		<!-- 资源与权限对应关系 -->
		<b:property name="securityMetadataSource" ref="mySecurityMetadataSource"></b:property>
	</b:bean>


</b:beans>

 

该文件就是spring security最主要的配置文件,该文件中配置了资源的访问权限,以及用户的来源。我们看到是从UserDetailsService来获取用户信息,然后再经过自定义过滤器myFilter来实现用户权限资源的管理。myFilter依赖于这三个类,authenticationManager,accessDecisionManager,securityMetadataSource,具体这三个类的Bean在下面这个配置中有配置,这三个Bean的作用在配置文件中有说明,这里就不在赘述。我用了两个配置文件目的就是把,Bean的配置放在applicationContext-common-business.xml文件中,spring security的配置文件只有引用,这样看起来结构更加清晰。也就是说下面的配置文件类似魏生产Bean的工厂。



3)applicationContext-common-business.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- - Application context containing business beans. - - Used by all artifacts. 
	- -->


<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<!-- 加载数据库资源文件 -->
	<context:property-placeholder location="classpath:dbconn.properties" />

	<!-- 扫描包,应用Spring的注解 -->
	<context:component-scan base-package="com.spring.security.dao" />

	<!-- 配置视图解析器,将ModelAndView及字符串解析为具体的页面 -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver"
		p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/security/"
		p:suffix=".jsp" p:contentType="text/html;charset=UTF-8" />

	<!-- 定义使用springframework数据源实现 -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!-- 指定连接数据库的驱动 -->
		<property name="driverClassName" value="${jdbc.driverClassName}" />
		<!-- 指定连接数据库的URl -->
		<property name="url" value="${jdbc.url}" />
		<!-- 指定连接数据库的用户名 -->
		<property name="username" value="${jdbc.username}" />
		<!-- 指定连接数据库的密码 -->
		<property name="password" value="${jdbc.password}" />
	</bean>

	<!-- 操作数据库的模板类 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<constructor-arg ref="dataSource"></constructor-arg>
	</bean>
	
	<!-- 配置userservice类 -->
	<bean id="myUserDetailService" class="com.spring.security.service.MyUserDetailService">
	    <property name="userCache" ref="userCache"/>
	</bean>

	<!-- 用户的密码加密或解密 -->
	<bean id="passwordEncoder"
		class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />

	<!-- 启用用户的缓存功能 -->
	<bean id="userCache"
		class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
		<property name="cache" ref="userEhCache" />
	</bean>

	<bean id="userEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
		<property name="cacheName" value="userCache" />
		<property name="cacheManager" ref="cacheManager" />
	</bean>

	<bean id="cacheManager"
		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
	
	<!-- 设置权限的前缀为AUTH_,而不是ROLE_。 
	<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter">
    	<property name="rolePrefix" value="ROLE_"/>
    </bean>
    -->
    
    <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源。 -->
	<bean id="myAccessDecisionManager" 
		class="com.spring.security.MyAccessDecisionManager"> </bean> 

	<!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色去访问。-->
	<bean id="mySecurityMetadataSource" 
		class="com.spring.security.MyInvocationSecurityMetadataSourceService">
		<constructor-arg name="resourcesDao" ref="resourcesDao"></constructor-arg>
	</bean>
</beans>

 
所有Bean类的配置



4)数据库资源文件dbconn.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/javaee
jdbc.username=root
jdbc.password=123


5)缓存配置文件ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

    <diskStore path="java.io.tmpdir"/>

    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
            
    <!-- set Category's Data expiration policies -->
    <cache name="org.qiujy.domain.cachedemo.Category"
    	maxElementsInMemory="100"
    	eternal="true"
    	timeToIdleSeconds="0"
    	timeToLiveSeconds="0"
    	overflowToDisk="false"
    />
    	
    <!-- set Category's productes Data expiration policies -->
    <cache name="org.qiujy.domain.cachedemo.Category.products"
    	maxElementsInMemory="500"
    	eternal="false"
    	timeToIdleSeconds="300"
    	timeToLiveSeconds="600"
    	overflowToDisk="true"
    />
    
    <!-- set Product's Data expiration policies -->
    <cache name="org.qiujy.domain.cachedemo.Product"
    	maxElementsInMemory="500"
    	eternal="false"
    	timeToIdleSeconds="300"
    	timeToLiveSeconds="600"
    	overflowToDisk="true"
    />
    
    <!-- set Default Data expiration policies -->
    <cache name="org.hibernate.cache.StandardQueryCache" 
       maxElementsInMemory="50"
       eternal="false" 
       timeToIdleSeconds="3600" 
       timeToLiveSeconds="7200" 
       overflowToDisk="true"
    />
    
    <!-- set customerQueries Data expiration policies-->
    <cache name="myCacheRegion"
        maxElementsInMemory="1000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
    />
    
    <!-- spring security's cache config. sparta 10/6/20 10:56 -->
    <cache
        name="userCache"
        maxElementsInMemory="100"
        eternal="false"
        timeToIdleSeconds="600"
        timeToLiveSeconds="3600"
        overflowToDisk="true"
    />
    
    <!-- spring security's acls cache config. sparta 10/6/22 15:41 -->
    <cache
    	name="aclCache"
    	maxElementsInMemory="1000"
    	eternal="false"
    	timeToIdleSeconds="600"
    	timeToLiveSeconds="3600"
    	overflowToDisk="true"
	/>
    
    
</ehcache>

 

 6)myFilter过滤用户请求

  (1)MyFilterSecurityInterceptor.java

public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor
		implements Filter {
	
	//与applicationContext-security.xml里的myFilter的属性securityMetadataSource对应,  
	//其他的两个组件,已经在AbstractSecurityInterceptor定义  
	@Autowired
	private FilterInvocationSecurityMetadataSource securityMetadataSource;

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		FilterInvocation fi = new FilterInvocation(request, response, chain);
		invoke(fi);

	}


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

	public void invoke(FilterInvocation fi) throws IOException,
			ServletException {
		// object为FilterInvocation对象  
		//super.beforeInvocation(fi);源码  
		//1.获取请求资源的权限  
		//执行Collection<ConfigAttribute> attributes = SecurityMetadataSource.getAttributes(object);  
		//2.是否拥有权限  
		//this.accessDecisionManager.decide(authenticated, object, attributes);  
		InterceptorStatusToken token = super.beforeInvocation(fi);

		try {
			fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
		} finally {
			super.afterInvocation(token, null);
		}

	}

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

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

	public void destroy() {

	}

	public void init(FilterConfig filterconfig) throws ServletException {

	}

}

 核心的InterceptorStatusToken token = super.beforeInvocation(fi);会调用我们定义的accessDecisionManager:decide(Object object)和securityMetadataSource

:getAttributes(Object object)方法。

  (2)MyInvocationSecurityMetadataSourceService.java

public class MyInvocationSecurityMetadataSourceService implements
		FilterInvocationSecurityMetadataSource {

	private ResourcesDao resourcesDao;

	// resourceMap及为key-url,value-Collection<ConfigAttribute>,资源权限对应Map
	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

	public MyInvocationSecurityMetadataSourceService(ResourcesDao resourcesDao) {
		this.resourcesDao = resourcesDao;
		System.out.println("加载MyInvocationSecurityMetadataSourceService..."
				+ resourcesDao);
		loadResourceDefine();
	}

	// 加载所有资源与权限的关系
	private void loadResourceDefine() {
		if (resourceMap == null) {
			resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
			List<Resource> resources = resourcesDao.findAll();
			//加载资源对应的权限
			for (Resource resource : resources) {
				Collection<ConfigAttribute> auths = resourcesDao
						.loadRoleByResource(resource.getRes_string());
				System.out.println("权限=" + auths);
				resourceMap.put(resource.getRes_string(), auths);
			}
		}
	}

	//加载所有资源与权限的关系
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		// object是一个URL,被用户请求的url
		String requestUrl = ((FilterInvocation) object).getRequestUrl();
		System.out.println("requestUrl is " + requestUrl);

		int firstQuestionMarkIndex = requestUrl.indexOf("?");

		if (firstQuestionMarkIndex != -1) {
			requestUrl = requestUrl.substring(0, firstQuestionMarkIndex);
		}

		if (resourceMap == null) {
			loadResourceDefine();
		}
		//
		Iterator<String> ite = resourceMap.keySet().iterator();

		while (ite.hasNext()) {
			String resURL = ite.next();

			if (resURL.equals(requestUrl)) {
				return resourceMap.get(resURL);
			}
		}
		return null;
	}

	@Override
	public boolean supports(Class<?> arg0) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		// TODO Auto-generated method stub
		return null;
	}

}


   (3)MyAccessDecisionManager.java

public class MyAccessDecisionManager implements AccessDecisionManager {

	@Override
	public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException, InsufficientAuthenticationException {

		if (configAttributes == null) {
			return;
		}

		//所请求的资源拥有的权限(一个资源对多个权限)
		Iterator<ConfigAttribute> ite = configAttributes.iterator();

		while (ite.hasNext()) {

			ConfigAttribute ca = ite.next();
			//访问所请求资源所需要的权限 
			String needRole = ((SecurityConfig) ca).getAttribute();
			System.out.println("needRole is " + needRole); 
			// ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。
			for (GrantedAuthority ga : authentication.getAuthorities()) {

				if (needRole.trim().equals(ga.getAuthority().trim())) {

					return;
				}

			}

		}
		//没有权限
		throw new AccessDeniedException("没有权限访问!");

	}

	@Override
	public boolean supports(ConfigAttribute arg0) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean supports(Class<?> arg0) {
		// TODO Auto-generated method stub
		return true;
	}

}

   (4)MyUserDetailService.java

/*
 * 该类的主要作用是为Spring Security提供一个经过用户认证后的UserDetails。
 *该UserDetails包括用户名、密码、是否可用、是否过期等信息。
 */
public class MyUserDetailService implements UserDetailsService {
	@Autowired
	private UserInfoDao userInfoDao;
	
	@Autowired
	private UserCache userCache;

	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		System.out.println("username is :" + username);

		Users user = null;
		try {
			user = this.userInfoDao.findByName(username);
			System.out.println(user);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// 获得用户权限
		Collection<GrantedAuthority> auths = userInfoDao
				.loadUserAuthorityByName(username);
		

		boolean enables = true;
		// 账户过期否
		boolean accountNonExpired = true;
		// 证书过期否
		boolean credentialsNonExpired = true;
		// 账户锁定否
		boolean accountNonLocked = true;
		// 封装成spring security的user
		User userdetail = new User(username, user.getPassword(), enables,
				accountNonExpired, credentialsNonExpired, accountNonLocked,
				auths);
		for (GrantedAuthority s : auths) {
			s.getAuthority();
		}
		System.out.println(auths);
		return userdetail;

	}

	public UserInfoDao getUserInfoDao() {
		return userInfoDao;
	}

	public void setUserInfoDao(UserInfoDao userInfoDao) {
		this.userInfoDao = userInfoDao;
	}

	//设置用户缓存功能。
	public UserCache getUserCache() {
		return userCache;
	}

	public void setUserCache(UserCache userCache) {
		this.userCache = userCache;
	}
	

}

 7)Dao组件

  1)ResourcesDao.java

@Repository
public class ResourcesDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;

	private static final Log log = LogFactory.getLog(UserInfoDao.class);

	public ResourcesDao() {
		System.out.println("加载ResourcesDao..." + jdbcTemplate);
	}

	public List<Resource> findAll() {
		try {
			List<Resource> resourceList = new ArrayList<Resource>();
			List<Map<String, Object>> resources = jdbcTemplate
					.queryForList("select * from resc");
			for (Map<String, Object> map : resources) {
				Resource r = new Resource();
				r.setId(Integer.valueOf(map.get("id").toString()));
				r.setName(map.get("name").toString());
				r.setRes_type(map.get("res_type").toString());
				r.setRes_string(map.get("res_string").toString());
				r.setDescn(map.get("descn").toString());
				resourceList.add(r);
			}

			return resourceList;
		} catch (RuntimeException re) {
			log.error("find all resource failed " + re);
			throw re;
		}
	}

	// 加载资源与对应的权限
	public Collection<ConfigAttribute> loadRoleByResource(String url) {
		try {
			String sql = "select ro.name as role,re.res_string as url "
					+ "from role ro join resc_role rr on ro.id=rr.role_id "
					+ "join resc re on re.id=rr.resc_id "
					+ "where re.res_string='" + url + "'";
			List<Map<String, Object>> authList = jdbcTemplate.queryForList(sql);
			Collection<ConfigAttribute> auths = new ArrayList<ConfigAttribute>();
			
			for(Map<String, Object> map:authList){
				ConfigAttribute auth = new SecurityConfig(map.get("role").toString());
				auths.add(auth);
			}
			
			return auths;
		} catch (RuntimeException re) {
			log.error("find roles by url failed " + re);
			throw re;
		}
	}

}

   2)UserInfoDao.java

@SuppressWarnings("deprecation")
@Repository
public class UserInfoDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;

	private static final Log log = LogFactory.getLog(UserInfoDao.class);
	
	public UserInfoDao(){
		loadSource();
		System.out.println("加载UserInfoDao..." + jdbcTemplate);
	}

	public Users findByName(String username) throws SQLException {
		String sql = "select * from user where username='" + username + "'";
		RowMapper<Users> mapper = new RowMapper<Users>() {
			@Override
			public Users mapRow(ResultSet rs, int rowNum) throws SQLException {
				Users user = new Users();
				user.setId((int) rs.getLong("id"));
				user.setUsername(rs.getString("username"));
				user.setPassword(rs.getString("password"));
				user.setStatus(rs.getInt("status"));
				user.setDescribtion(rs.getString("descn"));
				return user;
			}
		};

		System.out.println("怎么没有呢?");
		Users user = jdbcTemplate.queryForObject(sql, mapper);
		return user;
	}

	// 通过用户名获得权限集合
	public Collection<GrantedAuthority> loadUserAuthorityByName(String username) {
		try{
			List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
			
			List<String> authsList = loadUserAuthorities(username);
			
			for(String roleName:authsList){
				GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);
				auths.add(authority);
			}
			return auths;
		}catch(RuntimeException re){
			log.error("" + re);
			throw re;
		}
	}

	// 获取权限列表
	public List<String> loadUserAuthorities(String username) {
		try {
			String sql = "select r.name as authority "
					+ "from user u join user_role ur on u.id=ur.user_id "
					+ "join role r on r.id=ur.role_id " + "where u.username='"
					+ username + "'";
			List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
			List<String> roles = new ArrayList<>();
			for (Map<String, Object> map : list) {
				roles.add((String) map.get("authority"));
			}
			return roles;
		} catch (RuntimeException re) {
			log.error("find by authorities by username failed." + re);
			throw re;
		}
	}
	
	private void loadSource(){
		System.out.println("加载资源");
	}
}

 还有一些Domain类在此就省略不提了。以上就是笔者经过一个星期搞出来的,总算是能用了。

三.说明

1)容器启动(MySecurityMetadataSource:loadResourceDefine加载系统资源与权限列表)
2)用户发出请求
3)过滤器拦截(MySecurityFilter:doFilter)
4)取得请求资源所需权限(MySecurityMetadataSource:getAttributes)
5)匹配用户拥有权限和请求权限(MyAccessDecisionManager:decide),如果用户没有相应的权限,

执行第6步,否则执行第7步。
6)登录
7)验证并授权(MyUserDetailService:loadUserByUsername)
8)重复4,5

注:该流程为复制其他博客主的

四.结束

最后衷心的希望大家在程序员这条路上走得更远,更久,为我国软件行业做出一些贡献。

猜你喜欢

转载自xiaozhiwz.iteye.com/blog/1843329