码迷,mamicode.com
首页 > 数据库 > 详细

SpringSecurity数据库中存储用户、角色、资源

时间:2015-03-16 22:58:05      阅读:303      评论:0      收藏:0      [点我收藏+]

标签:

这几天项目中用到了SpringSecurity做登陆安全。所以在这写一下也许可以帮助一下其他人,自己也熟悉一下

SpringSecurity配置文件如下:

<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.1.xsd">
	
	<!-- 这个元素用来在你的应用程序中启用基于安全的注解 
    <global-method-security  pre-post-annotations="enabled" access-decision-manager-ref="myAccessDecisionManager"/>
    -->
	<http pattern="/index.html" security="none" />	
	
	<http auto-config="true">		
		<logout logout-success-url="/app/login" />
		<form-login login-page="/app/login" default-target-url="/app/admin"
			authentication-failure-url="/app/loginfailed" />
			
		<!-- "记住我"功能,采用持久化策略(将用户的登录信息存放在数据库表中) -->
		<!-- <remember-me data-source-ref="dataSource" /> -->
		
		<!-- 增加一个自定义的filter,放在FILTER_SECURITY_INTERCEPTOR之前,
		实现用户、角色、权限、资源的数据库管理-->
		<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/> 
		
	</http>
	
	<!-- 实现了UserDetailsService的Bean -->	
	<authentication-manager alias="myAuthenticationManager">
		<authentication-provider user-service-ref="myUserDetailService">
		     <password-encoder hash="plaintext">
             </password-encoder>		   
			<!-- <password-encoder ref="passwordEncoder">
			    <salt-source user-property="username" />
			</password-encoder> -->			 
		</authentication-provider>
	</authentication-manager>

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

 所有的实现逻辑便在这个FilterInterceptor之中,主要的实现的是这个Interceptor中的三个属性,而实现的这三个类:

Interceptor:

package com.yihaomen.common.intercept;

import java.io.IOException;

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.beans.factory.annotation.Autowired;
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 MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

	// 与spring-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 {

	}

}

 

package com.yihaomen.comm.service;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import com.yihaomen.common.dao.ResourcesDao;
import com.yihaomen.common.domain.SysResource;

public class MyInvocationSecurityMetadataSourceService implements
		FilterInvocationSecurityMetadataSource {

	@Autowired
	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<SysResource> resources = resourcesDao.findAll();
			// 加载资源对应的权限
			for (SysResource resource : resources) {
				Collection<ConfigAttribute> auths = resourcesDao
						.loadRoleByResource(resource.getResource());
				System.out.println("权限=" + auths);
				resourceMap.put(resource.getResource(), auths);
			}
		}
	}

	//由资源路径获得权限
	//object为请求的资源路径
	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;
	}

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

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

}

 

package com.yihaomen.comm.service;

import java.sql.SQLException;
import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.yihaomen.common.dao.UserInfoDao;
import com.yihaomen.common.domain.SysUser;
/**
 * 根据用户名获得其所拥有的权限,返回该用户的状态信息。并将其所拥有的权限放入GrantedAuthority中
 * @author Administrator
 *
 */
public class MyUserDetailService implements UserDetailsService {
	@Autowired
	private UserInfoDao userInfoDao;
	
	@Autowired
	private UserCache userCache;

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

		SysUser 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;
	}
	

}

 

package com.yihaomen.comm.service;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

public class MyAccessDecisionManager implements AccessDecisionManager {

	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("没有权限访问!");

	}

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

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

}

 

SpringSecurity数据库中存储用户、角色、资源

标签:

原文地址:http://www.cnblogs.com/betterthisworld/p/4343072.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!